1. 从一根天线到一串比特:这条链路到底在做什么
把一台 P201Pro 插上电脑,打开 GNU Radio,拖几个模块连起来,屏幕上就能看到 QPSK 的星座点簇——这件事听起来像是"点几下鼠标"的活儿,但真正做过的人都知道,从射频前端到最终那团点簇,中间隔着一条相当长的信号处理链路,任何一环出问题,你看到的要么是噪声,要么是一团糊在一起的毛线球。
我前后用 P201Pro 配合 GNU Radio 搭过几轮收发链路,从最开始连不上设备,到后来能稳定看到清晰的 QPSK 星座图,中间踩的坑足够写一篇完整的复盘。这篇就把整条链路拆开讲清楚:P201Pro 这块基于 AD9361 的 SDR 板子,在 GNU Radio 里到底是怎么把空中的电磁波变成一个个复数采样点,再变成 QPSK 符号,最后在星座图上呈现出那四个点簇的。
先说清楚这套东西适合谁看。如果你刚拿到一块 SDR 板子,想跑通第一个收发链路,这篇能帮你少走至少两天的弯路;如果你已经能跑出波形但星座图总是不干净,这篇里的滤波器配置、增益分配、同步环节的细节应该能对上你的症状;如果你只是想理解 AD9361 这类射频捷变收发器的工作原理,那从零中频架构到数字接口这一段也值得一读。
P201Pro 这类板子的核心是 AD9361,一颗集成了 RF 前端、混频器、ADC/DAC、数字滤波器的射频捷变收发芯片。它的可调谐范围覆盖 70 MHz 到 6 GHz,通道带宽可配置,支持 2x2 MIMO。GNU Radio 这边通过 IIO(Industrial I/O)驱动跟它通信,把采样数据搬进主机内存,剩下的解调、同步、判决全在软件里完成。所以整条链路的本质是:硬件负责把射频信号搬到基带并数字化,软件负责把数字流还原成符号。
理解这个分工很重要,因为它决定了你排查问题的方向。星座图不对,可能是硬件侧的增益或本振没配好,也可能是软件侧的同步没收敛,还可能是两者之间的采样率对不上。后面我会按信号流动的顺序,一段一段拆。
2. AD9361 初始化:那些让人抓狂的寄存器与锁定状态
2.1 为什么初始化失败往往卡在 PLL 锁定
AD9361 上电之后并不是立刻就能用的,它需要一整套初始化流程:配置时钟、设置本振频率、校准、等待 PLL 锁定。这里面最容易出问题的就是RX PLL 和 TX PLL 的锁定。PLL 锁不住,本振频率就是错的,你收到的信号根本不在你期望的频点上,星座图自然是一团噪声。
我遇到过最典型的一个现象:初始化过程中 RX PLL 一直没有锁定标志,同时 CP(Charge Pump,电荷泵)的过压标志 CP OVRG 被置高。这两个现象经常一起出现,而且指向的是同一个根因——电荷泵的电流配置和环路滤波器参数不匹配,导致环路无法进入锁定状态。
电荷泵是 PLL 里把鉴相器输出的相位误差转换成电流的部分,这个电流去充放环路滤波器上的电容,进而控制 VCO 的频率。如果电荷泵电流设得太大,环路滤波器上的电压会冲过头,触发过压保护;设得太小,环路增益不够,锁定时间会变得极长甚至锁不住。AD9361 内部有一套自动校准机制,但前提是你的参考时钟和配置参数在合理范围内。
2.2 参考时钟:一切的地基
AD9361 的 PLL 需要一个参考时钟,这个时钟通常来自板载的晶振或者外部输入的参考。P201Pro 这类板子一般板载一个 40 MHz 的晶振作为默认参考。如果你的初始化配置里参考时钟频率写错了,比如实际是 40 MHz 你配成了 38.4 MHz,那所有基于这个参考推导出来的本振频率都会偏,PLL 也可能因为鉴相器一直看到固定相位误差而锁不住。
排查这一步的方法很直接:确认板子的实际晶振频率,然后在初始化脚本或设备树里核对。GNU Radio 的 IIO 模块在连接设备时会读取一些属性,你可以通过iio_info命令把设备的属性树打印出来,重点看sampling_frequency、rf_bandwidth、xo_correction这些字段的实际值。
提示:
xo_correction这个属性很多人会忽略。它是对参考晶振的频率修正,单位是 ppb(十亿分之一)。如果你的晶振有偏差,或者你想用外部参考,这个值需要相应调整。默认值不一定适合你的板子。
2.3 滤波器配置:别让工具替你做了错误的决定
AD9361 内部有多个数字滤波器:RX 侧的 FIR、HB(半带)滤波器、DEC(抽取)滤波器,TX 侧的对应镜像。这些滤波器的系数决定了通道的带宽和带外抑制。ADI 官方提供了一个滤波器设计工具(Filter Wizard),输入你的采样率、通道带宽、通带纹波、阻带衰减这些指标,它会生成一组系数。
这里有个坑我踩过:滤波器工具生成的系数是给特定采样率用的,如果你在 GNU Radio 里改了采样率但没重新生成系数,滤波器的实际响应就会偏。表现出来就是星座图上的点簇边缘发散,EVM 变差,但你又找不到明显的噪声源。
正确的做法是:先确定你的符号率和所需的通道带宽,反推出采样率,然后用这个采样率去生成滤波器系数,最后在初始化时把系数写进 AD9361。采样率、通道带宽、滤波器系数这三者是绑定的,改一个就要重新算另外两个。
2.4 一个实用的初始化检查清单
把初始化流程拆成可检查的步骤,能省下大量瞎猜的时间:
| 检查项 | 期望状态 | 常见异常 |
|---|---|---|
| 参考时钟频率 | 与板载晶振一致 | 配错导致全频偏 |
| RX PLL 锁定 | 锁定标志置位 | CP OVRG 置高、锁不住 |
| TX PLL 锁定 | 锁定标志置位 | 同上 |
| 采样率 | 与软件侧一致 | 不一致导致采样点错位 |
| 通道带宽 | 覆盖信号带宽 | 过窄导致信号被削 |
| 滤波器系数 | 与采样率匹配 | 不匹配导致响应偏移 |
| 增益模式 | 手动或自动 | 自动模式下增益跳变 |
这张表我基本每次搭新链路都会过一遍,尤其是换了采样率或者换了频段之后。AD9361 的初始化不是"配一次就永远对"的事情,参数之间耦合很紧。
3. GNU Radio 里的采样流:从 IIO 源到复数基带
3.1 IIO Source 到底吐出来的是什么
GNU Radio 里连接 P201Pro 的模块叫IIO Source(或者在某些版本里叫FMComms2 Source)。它的输出是复数采样点,每个点是一个complex float,实部是 I 路,虚部是 Q 路。这一点很关键:AD9361 输出的就是零中频的 I/Q 信号,不需要你在软件里再做下变频。
零中频架构的好处是省去了中频这一级,ADC 直接采基带的 I/Q。但代价是会有直流偏移和 I/Q 不平衡的问题。直流偏移表现为星座图整体偏离原点,I/Q 不平衡表现为星座图被"压扁"成椭圆而不是正圆。这两个问题在 AD9361 内部有校准机制可以缓解,但不可能完全消除,软件侧有时还需要再做一次直流阻塞和 I/Q 校正。
IIO Source的几个关键参数:
- 采样率(Sample Rate):这是 ADC 的采样率,也是 GNU Radio 里这个模块的输出速率。它必须和 AD9361 内部配置的采样率一致。
- 中心频率(Center Frequency):本振频率,决定你接收哪个频段。
- RF 带宽(RF Bandwidth):模拟前端的带宽,一般设成和信号带宽相当或略宽。
- 增益(Gain):接收增益,手动模式下是一个固定值,自动模式下 AD9361 会根据信号强度调整。
我一般先把增益设成手动,给一个中间值(比如 40 dB 左右),等链路跑通了再根据实际信号强度微调。自动增益在调试阶段是个麻烦,因为它会随着信号变化跳来跳去,你很难判断星座图的变化到底是增益引起的还是别的原因。
3.2 采样率的选择:别只看符号率
很多人第一次配采样率的时候会想:QPSK 符号率是 1 Msps,那我采样率设 1 MHz 不就行了?不行。采样率必须大于符号率,通常至少是符号率的 2 到 4 倍,这是为了给后续的匹配滤波和定时同步留出余量。
假设你的 QPSK 符号率是 1 Msps,每个符号用 4 个采样点表示,那采样率就是 4 MHz。这个"每符号采样数"(samples per symbol, sps)是个很重要的参数,它直接影响后续的定时同步精度。sps 太小,定时误差的估计会不准;sps 太大,计算量上去了但精度提升有限。实践中 2 到 8 之间比较常见,4 是个不错的起点。
采样率定了之后,AD9361 的抽取滤波器配置也要跟着改。AD9361 的采样率是通过一系列抽取/插值滤波器从内部的高采样率降下来的,每一级的抽取比都要配置正确,最终的输出采样率才是你想要的。这一块如果配错,实际输出速率和软件以为的速率对不上,星座图会以某种规律"旋转"或者"漂移"。
3.3 一个容易忽略的细节:采样率不是随便设的
AD9361 的采样率有它的合法范围,而且和参考时钟、滤波器配置有关。你不能随便设一个 3.14159 MHz 这样的值。一般来说,采样率应该是参考时钟经过一系列整数分频/倍频能得到的值。P201Pro 板载 40 MHz 参考的话,常见的合法采样率是 40 MHz 除以某个整数,或者经过 PLL 倍频后再分频得到的值。
如果你在 GNU Radio 里设了一个 AD9361 不支持的采样率,驱动可能会静默地把它设成最接近的合法值,而软件侧还以为是你设的值。这种"静默修正"是最难查的,因为没有任何报错,但采样率就是不对。所以设完采样率之后,一定要用iio_info或者类似的工具回读一下实际值,确认和你设的一致。
4. QPSK 解调链路:同步才是真正的硬骨头
4.1 匹配滤波与符号定时
从IIO Source出来的复数流,第一步通常是匹配滤波。匹配滤波器的目的是最大化信噪比,对于 QPSK 这种矩形脉冲成形的信号,匹配滤波器就是一个和脉冲形状共轭的滤波器。实际中常用的是根升余弦(RRC)滤波器,发射端和接收端各用一个,合起来就是升余弦响应。
匹配滤波之后是符号定时同步。因为接收端的采样时钟和发射端不是同一个时钟,采样点不会正好落在符号的最佳判决点上,总会有定时偏差。符号定时同步的任务就是估计这个偏差,然后在正确的位置上抽取符号。
GNU Radio 里常用的符号同步模块是Polyphase Clock Sync或者Symbol Sync。Polyphase Clock Sync用的是多相滤波器组的方法,精度不错但计算量大;Symbol Sync是后来引入的,支持多种定时误差检测算法,配置更灵活。
这里有个经验:定时同步的环路带宽要设得合适。带宽太宽,同步收敛快但抖动大;带宽太窄,收敛慢但稳态抖动小。对于连续传输的信号,可以设窄一点;对于突发信号,得设宽一点让它快速收敛。我一般从归一化带宽 0.01 左右开始试,根据星座图的收敛情况调整。
4.2 载波同步:星座图旋转的元凶
符号定时解决的是"什么时候采样"的问题,载波同步解决的是"相位对不对"的问题。发射端和接收端的本振不可能完全同频同相,总会有一个频率偏差和相位偏差。频率偏差会让星座图持续旋转,相位偏差会让星座图整体转一个固定角度。
载波同步通常分两步:粗同步和细同步。粗同步用 FFT 或者基于已知序列的方法估计大频偏,细同步用锁相环(PLL)跟踪残余的相位误差。GNU Radio 里的Costas Loop是 QPSK 常用的载波跟踪环,它对 BPSK 和 QPSK 都适用。
Costas Loop的关键参数是环路带宽。和定时环一样,带宽的选择是收敛速度和稳态抖动之间的权衡。QPSK 有个特殊性:它有 90 度的相位模糊,也就是说 Costas Loop 锁定之后,星座图可能整体旋转了 0、90、180 或 270 度。这个模糊需要靠差分编码或者已知的同步序列来消除。
我实测下来,如果星座图在旋转,八成是载波频偏没补干净;如果星座图不转但整体偏了一个角度,那是相位偏差;如果星座图四个点簇的位置对,但点簇本身发散,那问题在信噪比或者 I/Q 不平衡上。根据星座图的"症状"反推问题环节,是调试这条链路最有效的方法。
4.3 帧同步与判决
载波同步之后,信号已经是一个个比较干净的复数符号了。接下来是帧同步——找到数据帧的起始位置。这通常靠一个已知的同步序列(比如前导码)来做互相关,相关峰出现的位置就是帧头。
帧同步之后就是判决:把每个复数符号映射回最近的星座点。QPSK 有四个星座点,分别在 (1,1)、(-1,1)、(-1,-1)、(1,-1) 的方向上(归一化之后)。判决就是看接收到的符号离哪个点最近,就判成哪个点,然后映射回对应的两比特。
判决之后可以算误码率(BER)或者误差向量幅度(EVM)。EVM 是衡量星座图质量的一个综合指标,它把每个符号和理想星座点的偏差归一化之后统计。EVM 越小,星座图越干净,解调质量越好。
5. 星座图诊断:从点簇形态反推链路问题
5.1 四种典型"病态"星座图
星座图是这条链路最直观的体检报告。我整理了几种常见的异常形态和对应的可能原因:
| 星座图形态 | 可能原因 | 排查方向 |
|---|---|---|
| 四个点簇糊成一团 | 信噪比太低 | 增益、天线、干扰 |
| 点簇呈椭圆而非圆形 | I/Q 不平衡 | 前端校准、软件校正 |
| 整体偏离原点 | 直流偏移 | 直流阻塞滤波 |
| 持续旋转 | 载波频偏未补 | Costas Loop 带宽、频偏估计 |
| 点簇边缘发散呈"云状" | 相位噪声大 | 本振质量、环路带宽 |
| 只有两个点簇清晰 | 相位模糊或判决错误 | 差分编码、同步序列 |
这张表是我调试时的"对症下药"参考。每次星座图不对,先看它属于哪种形态,然后往对应的方向查,比盲目调参数效率高得多。
5.2 增益分配:一个被低估的调试变量
接收链路的增益分配对星座图的影响非常大,但很多人调的时候只盯着软件参数,忽略了硬件增益。AD9361 的接收增益分几级:LNA(低噪声放大器)、混频器、TIA(跨阻放大器)、ADC 前的 PGA。每一级的增益都可以单独调,总的增益是各级之和。
增益太低,信号淹没在噪声里,星座图糊;增益太高,ADC 饱和,星座图会被"削顶",出现非线性失真。理想的状态是让 ADC 的输入信号幅度占满量程的 70% 到 80%,既充分利用了 ADC 的动态范围,又留了余量防止饱和。
判断 ADC 是否饱和,可以看IIO Source输出的采样值有没有频繁触及最大最小值。如果经常触顶,就得降增益。这个在 GNU Radio 里可以用一个简单的幅度统计模块来观察。
5.3 采样率不匹配的隐蔽症状
采样率不匹配是个很隐蔽的问题,因为它的症状不总是那么明显。如果软件侧的采样率和硬件实际输出速率不一致,你会看到星座图以某种规律缓慢漂移或者周期性抖动。这种漂移和载波频偏引起的旋转不一样:频偏引起的旋转是匀速的,采样率不匹配引起的漂移往往带有周期性或者和某种节拍相关。
排查方法是:发一个已知的测试信号(比如单音或者已知序列),看接收端解出来的符号速率和预期是否一致。如果符号速率有系统性偏差,那基本就是采样率的问题。回到 AD9361 的配置,核对抽取滤波器链的每一级设置,确保最终输出速率和软件侧一致。
6. 几个让我印象深刻的坑与对应的解法
6.1 CP OVRG 置高与 PLL 不锁定的连锁反应
前面提到过 CP OVRG 和 PLL 不锁定经常一起出现。我第一次遇到的时候,以为是芯片坏了,折腾了很久。后来才明白这是电荷泵电流和环路滤波器不匹配导致的。
AD9361 的 PLL 环路滤波器参数是可以通过寄存器配置的,但大多数情况下用默认值就行。如果你改了参考时钟频率或者本振频率范围,可能需要相应调整。CP OVRG 置高说明电荷泵输出的电压超过了某个阈值,这通常意味着环路在试图用很大的电流去纠正一个它纠正不了的误差。
解法是:先确认参考时钟频率正确,然后检查本振频率是否在合法范围内,最后如果还不行,尝试调整电荷泵电流设置。ADI 的驱动里通常有自动校准流程,确保这个流程完整执行了,不要中途打断。
6.2 滤波器系数写错导致的"幽灵"干扰
有一次我换了采样率,但忘了重新生成滤波器系数。结果星座图看起来还行,但 EVM 一直下不去,而且频谱上能看到一些不该有的杂散。查了很久才发现是滤波器响应和采样率不匹配,导致带外的一些分量没有被充分抑制,混叠进了带内。
这个坑的教训是:采样率、通道带宽、滤波器系数是一个整体,改任何一个都要重新审视另外两个。我现在养成的习惯是,每次改采样率,都重新跑一遍滤波器设计工具,把新系数写进去,然后再回读确认。
6.3 自动增益带来的"薛定谔"星座图
调试初期我用的是自动增益,结果星座图时好时坏,同一个配置有时候清晰有时候糊。后来关掉自动增益改手动,问题立刻定位了——是增益在信号强度变化时跳变,导致 ADC 的工作点不稳定。
自动增益在最终产品里是有用的,它能适应信号强度的变化。但在调试阶段,它引入了一个你控制不了的变量,让问题定位变得困难。调试时用手动增益,把变量固定住,等链路跑通了再考虑要不要开自动增益。
6.4 天线与连接器的"低级"问题
说出来有点丢人,但我确实遇到过因为天线没拧紧导致星座图一塌糊涂的情况。射频连接器的接触不良、线缆的损耗、天线的驻波比,这些"低级"问题在调试时反而容易被忽略,因为大家都倾向于往复杂的数字信号处理方向想。
所以我的建议是:在怀疑软件之前,先确认硬件连接没问题。用频谱仪或者功率计看一下发射端的输出功率,用已知良好的天线和线缆,排除掉这些基础问题之后再深入软件。
7. 把这条链路跑稳之后的一些体会
整条链路跑通之后回头看,最花时间的不是写 GNU Radio 的流图,而是理解 AD9361 的配置逻辑和各个参数之间的耦合关系。GNU Radio 的模块拖拖拽拽很快,但每个模块的参数背后都有它的物理意义,不理解这些意义,调参就是碰运气。
我现在搭新链路的顺序基本固定下来了:先确认硬件连接和参考时钟,再配 AD9361 的采样率和滤波器,然后用一个简单的单音信号验证收发通路,确认采样率一致、增益合理,最后才上 QPSK 的完整解调链路。这个顺序的好处是每一步都有明确的验证标准,出了问题能快速定位到是哪一步引入的。
星座图这个东西,看多了会有直觉。干净的 QPSK 星座图应该是四个紧凑的圆形点簇,对称分布在四个象限,点簇之间界限清晰。一旦形态偏离这个理想状态,就说明链路里某个环节有问题。把星座图的形态和链路的环节对应起来,是这套东西从"能跑"到"跑得好"的关键。
最后分享一个我常用的小技巧:在 GNU Radio 里加一个Constellation Sink的同时,再加一个QT GUI Time Sink看时域波形,加一个QT GUI Frequency Sink看频谱。三个视图一起看,时域看幅度和定时,频域看带宽和杂散,星座图看解调质量,互相印证,比只看一个视图能更快地定位问题。