把随机比特送进流图,经过QPSK映射、脉冲成型、上变频,最后从P201Pro的天线口发出去;接收端再一路解调回来,在屏幕上看到四个清晰分开的点簇——这一瞬间,数字通信前面几章教材突然就活了。这是软件无线电系列实验的第四篇,也是一次阶段性总结。前三篇我们分别啃下了环境搭建、基带模块验证和频谱观测,这次不再只盯单个模块,而是把“bit流到QPSK点簇”这条完整链路串起来。
这篇文章写给两类人:一类是刚接触GNU Radio和AD9361平台、想跑通端到端收发但不知道从哪下手的同学;另一类是已经能看见星座图、但点簇不收敛或者总在转圈、想系统排查问题的实践者。全文围绕P201Pro在GNU Radio里的发射链路、接收链路、参数计算和实测踩坑展开,所有内容都基于AD9361方案的通用行为,换成同族硬件也能平移。
1. P201Pro与AD9361:先搞清楚硬件在链路里的位置
软件无线电实验最容易翻车的地方,不是GNU Radio流图画不对,而是压根没搞懂板卡在“比特到空中”这条链路里承担了什么角色。P201Pro这类板子,核心是一颗AD9361射频收发芯片,加上一片Zynq负责控制和数据搬运,对外提供以太网/USB接口给上位机。把它想成“一台可编程对讲机加一张高速声卡再配一块FPGA”,可能更贴近实际。
1.1 射频收发芯片不是“一次做完所有事”
AD9361把混频器、滤波器、AGC、ADC/DAC都集成进去了,但基带调制解调仍然要靠GNU Radio在CPU里完成。也就是说,GNU Radio负责的是“0和1变成IQ波形、IQ波形变成0和1”的数学过程,AD9361负责的是“IQ波形搬到某个频率发出去、把空中的信号搬下来变成IQ”。这个分工一旦想清楚,很多流图配置就不会再纠结。
我在实验里习惯先画一张信号流向草图:bit → symbol → 基带IQ波形 → DAC → 混频 → 天线;接收反过来:天线 → 混频 → ADC → 基带IQ → 同步 → symbol → bit。P201Pro只负责中间的射频模拟部分,剩下的都是GNU Radio流图的事。这也是“软件无线电”这个概念的真正含义——硬件尽量通用,功能靠软件定义。
1.2 AD9361的关键参数与配置约束
用GNU Radio对接P201Pro时,你迟早要面对这几个参数:中心频率、采样率、信道带宽、TX增益/衰减、RX增益。AD9361的工作频率范围是70MHz到6GHz,信道带宽支持200kHz到56MHz,ADC/DAC是12位。具体到实验里,最常用的配置逻辑是这样的:
- 中心频率:选一个合法且干扰少的频段,实验常用2.45GHz附近的ISM频段;
- 采样率:GNU Radio流图的采样率要和板卡ADC/DAC采样率对齐,通常设为符号速率的整数倍;
- 信道带宽:设成略大于信号实际占用带宽,别太宽,宽了把带外噪声和干扰都收进来;
- TX增益:通过衰减值控制,AD9361的TX衰减范围0~89.75dB,步进0.25dB;
- RX增益:手动或AGC都行,短距离实验建议手动,方便排查问题。
下面这组参数是我在P201Pro上跑通QPSK收发时用的基准配置,后面所有计算都围绕它展开:
| 参数 | 数值 | 说明 |
|---|---|---|
| 中心频率 | 2.45 GHz | ISM频段,天线和功放都好找 |
| 符号速率 Rs | 1 Msps | 低速利于观察和排查 |
| 采样率 Fs | 10 MHz | 每符号10个采样点 |
| 滚降系数 α | 0.35 | 常用折中值 |
| 信号占用带宽 | 1.35 MHz | 双边带宽 = (1+α)×Rs |
| AD9361信道带宽 | 2 MHz | 略大于信号带宽即可 |
1.3 和AD-FMCOMMS5-EBZ这类评估板的关系
如果你手头正好是ADI官方的ad-fmcomms5-ebz评估板,或者别的AD9361方案板卡,这篇实验的结论基本都能平移过去。区别只在于驱动入口:P201Pro通常通过厂商适配的SoapySDR或IIO接口接入GNU Radio,FMCOMMS5用gr-iio,但流图里你看到的模块名字、参数含义、同步环路的调法都是一样的。
我自己的体会是,不要被板卡型号带偏思路。AD9361方案有一套“通用脾气”:采样率要匹配、增益不能贪、本振锁定需要时间、频率误差要靠同步环拉回。把这些脾气摸熟,换板子只是改改设备名和接口参数的事。
2. 发射端流图:从随机bit到基带IQ波形
这一节是整条链路里最好验证、也最容易理解的部分。因为发射端不需要面对同步问题,你给什么比特,它就老老实实映射成什么IQ点,再按脉冲成型滤波送出去。在GNU Radio里搭这条链路,能让“比特到符号到波形”的每一步都看得见摸得着。
2.1 为什么要从“比特”开始讲故事
通信系统最底层的输入是二进制比特,但物理层不能直接传输比特,它只能传输波形。QPSK做的事情,就是把每2个比特映射成4个相位之一,然后把这4个相位编码成同相和正交两路电压。一句话:比特是“语义”,符号是“物理层的字母”。
实验里我用随机比特源,而不是固定图案,原因很简单——随机比特能让星座图上的四个点均匀出现,便于观察统计特性。如果你用固定序列,星座图上可能长时间只有一两个点,看起来像没调好。随机源加足够长的观测时间,四个点簇才会稳定呈现。
2.2 流图的模块组成与参数设置
在GNU Radio Companion里,发射端我习惯这样搭模块链:
- Random Source(Byte输出),产生随机比特;
- Throttle,限制流图速率,防止CPU空转把CPU跑满;
- Chunks to Symbols,把比特按QPSK映射成复数符号;
- Root Raised Cosine Filter,脉冲成型,限制信号带宽;
- Multiply Const,调整幅度到合适范围;
- 板卡Sink模块(SoapySDR Sink或IIO Sink),设置中心频率、采样率、TX增益。
重点说Chunks to Symbols这一步。它本质是一个查表器,2个bit查一个复数符号。QPSK的Gray映射表我这样定义:
- 00 → 1 + 1j(45度)
- 01 → -1 + 1j(135度)
- 11 → -1 - 1j(225度)
- 10 → 1 - 1j(315度)
用Gray映射的好处是相邻相位只差1个bit,即便误判到邻居符号,也只错1个bit,而不是2个。这个细节在实验里看不出差别,但如果你后面做BER测试,Gray映射能让误码率直接减半。
2.3 脉冲成型:为什么不能直接发方波符号
很多人第一次搭发射端,想省掉Root Raised Cosine Filter,直接把符号电平送进DAC。结果就是频谱占用很宽、相邻符号互相干扰,接收端星座图全部糊在一起。这就是码间串扰(ISI)——符号波形拖尾窜到相邻符号的时间槽里。
奈奎斯特第一准则告诉我们,要无ISI传输,脉冲的频域特性要满足特定的滚降条件。根升余弦(RRC)滤波器就是为此设计的。发送端用RRC成型,接收端再用一个同样的RRC做匹配滤波,两个级联起来等效于升余弦脉冲,在最佳采样点上正好做到“自己不拖尾、不踩邻居”。
滚降系数α影响带宽和拖尾衰减速度。α越大,带宽越宽但拖尾衰减越快,对定时误差越不敏感;α越小,带宽越窄但拖尾衰减越慢,定时稍微偏一点点簇就散。我用0.35作为折中。信号双边带宽按(1+α)×Rs计算,也就是1.35MHz。AD9361的信道带宽设2MHz,留出约0.65MHz的过渡带余量。
RRC滤波器的抽头数也很关键。在GNU Radio里我设Number of Taps为符号周期的整数倍,例如每个符号10个采样,抽头数设6×11,意思是在符号两侧各留6个符号周期的拖尾余量。抽头太少,滤波器的频响不够“方”,带外抑制差;抽头太多,延迟和CPU开销都上去了,实验里没必要追求极致。
2.4 发射端最后一个细节:幅度控制
基带IQ波形在进DAC之前,要乘一个幅度因子。这步很多人忽略,直接默认1.0,结果AD9361的DAC可能饱和,或者发射链路增益余量不够。我通常会先用波形观察一下基带IQ的峰值幅度,再调整Multiply Const,确保信号峰值不超过DAC满量程的60%~70%。
后面在射频端还有独立的TX衰减控制。这两个旋钮要配合用:基带幅度管“波形本身有多大”,TX衰减管“射频放大器给多少增益”。实验里常见错误是基带幅度拉满、TX衰减又设为0,结果发射链路过驱动,星座图外围出现奇怪的卷曲或毛刺。
3. 从基带到射频:P201Pro发射链路真正“出门”之前
基带IQ波形在GNU Radio里是完美的数学对象,一旦经过P201Pro的DAC、混频器和功放,就会遇到现实世界的所有麻烦:本振泄漏、IQ不平衡、增益非线性、频率偏移。这一节说的是把信号送进射频前端时,需要考虑哪些实际问题。
3.1 LO频率与信道带宽规划
中心频率选2.45GHz,不是随便拍的。这个频段设备多、干扰也杂,但优势是天线、衰减器、功放这些配件最容易找到,而且我的经验是2.4G WiFi频段虽然拥挤,但做1MHz符号率的窄带信号只要挑个相对干净的频率点,影响有限。选频时在GNU Radio里用Freq Sink先扫一遍底噪,挑一个没有明显强信号的频点。
AD9361的信道带宽设置会影响接收端的抗干扰能力。太宽会把带外噪声收进来,降低信噪比;太窄会切掉信号边缘。我按信号占用带宽的1.3~1.5倍来设,QPSK 1Msps、α=0.35时设2MHz就够。这个配置在P201Pro上实测,星座图的点簇扩散程度和理论值基本吻合。
3.2 TX增益:不是越大越好
AD9361的发射功率是通过“衰减量”来控制的,范围0到89.75dB。很多人以为衰减越小信号越强越好,实则不然。我踩过的坑是:把TX衰减设为0,短距离对着接收板发,结果接收端星座图非但没更清晰,反而边缘出现一圈扩散。查了半天才明白,是发射链路末级放大器进入了饱和区,产生非线性失真。
实验里我习惯从衰减20dB左右开始,看接收端星座图能锁住、点簇收敛,再逐步减小衰减找最优。判断标准不是“信号最强”,而是“星座图散点半径最小”。这中间通常存在一个甜点区:继续加大TX增益,星座图开始变坏,说明非线性已经压过信噪比收益。
3.3 先别急着上天线:发射-接收自环验证
把发射端流图和接收端流图都搭好后,第一件事不是把信号发到空中,而是用射频线缆把TX口和RX口直接连起来,中间加30dB衰减器。这一步能单独验证“射频链路是否正常”,把空间信道这个变量彻底排除。
自环验证通过的标准有三个:星座图出现四个清晰点簇、点簇不旋转、接收比特和发送比特基本一致。我在P201Pro上做自环时,如果连这些都达不到,问题基本锁定在GNU Radio流图本身或者参数配置上,跟天线、多径、干扰都无关。等自环完全通过,再拆掉线缆换成天线,才能把新出现的问题归因于空间信道。
3.4 收发时钟要不要共源,这是个问题
P201Pro板卡内部有晶振,两块板卡各自独立工作时,发射板的10MHz参考和接收板的10MHz参考并不完全一致,会带来约±几ppm的载波频率误差。对QPSK来说,这个误差落在Costas环的捕获范围内时问题不大;但如果误差太大,或者符号速率很低导致相位旋转速度可观,点簇就会转圈。
实验里最省事的办法是让两块板子共用一个10MHz参考时钟,把P201Pro的参考时钟输入用功分器接同一个源。没有条件共源时,就把接收端的载波粗同步模块(Frequency Xlating FIR Filter)加上,先手动找频偏再交给Costas环细调。共源这个细节,真的能让你少排查半小时。
4. 接收端流图:把四个点簇从噪声和频偏里“捞”出来
接收端是整个实验里模块最多、调试经验最密集的部分。信号到了接收端,经历了信道衰减、多径、频偏、采样钟偏差,已经面目全非。GNU Radio接收链路的任务,就是一步步把这些“脏东西”清理掉,让星座图重新显出本来面目。
4.1 接收链路的模块顺序与理由
我搭的接收链路是这种顺序:
- 板卡Source(SoapySDR Source或IIO Source),设置中心频率2.45GHz、采样率10MHz、RX增益;
- Frequency Xlating FIR Filter,用于粗频偏校正,把信号频谱搬到零频附近;
- Root Raised Cosine Filter,作为匹配滤波,和发射端的成型滤波配对;
- Polyphase Clock Sync或Symbol Sync,做符号定时同步;
- Costas Loop,做载波同步,消除残余频偏和相位偏移;
- Constellation Sink,观察星座图。
这个顺序不是随便排的。匹配滤波要在定时同步之前,因为定时同步需要“干净”的符号波形来计算最佳采样点;Costas环放在定时同步之后,是因为符号级定时恢复后,相位误差更接近恒定值,环路更容易锁定。粗频偏校正放在最前面,是为了减轻后面Costas环的负担——它只能捕获一定范围内的频偏,超了就转圈。
4.2 两个同步环在暗地里替你做的事
把定时同步和载波同步讲清楚,是理解接收端的关键。
定时同步解决的是“什么时候采样”。发射端每个符号等间隔发出去,但接收端采样时钟和发射端有偏差,而且信号经过信道延迟后,符号边界的位置是未知的。Polyphase Clock Sync模块用一组多相滤波器插值,实时估计最佳采样时刻,在每个符号的“峰尖”上采样。这个模块在GNU Radio里的参数要设对:Symbol Rate设1M,Samples per Symbol设10,Loop Bandwidth别太大,太大抖动,太小锁定慢。
Costas环解决的是“载波相位到底是多少”。QPSK信号在接收端经过混频后,本地振荡和发射振荡的频率、相位都有误差,星座点整体会旋转。Costas环用余弦鉴相器估计相位误差,通过环路滤波器反馈给NCO持续修正。它的输出特性是:相位模糊为90度整数倍,也就是解调出的符号可能整体旋转了0、90、180或270度。这是QPSK载波恢复的固有问题,后面用差分编码或者已知帧头来消除。
4.3 星座图用什么参数看,以及“点簇合格”的标准
Constellation Sink看起来只是画点,但参数设置影响你能否看出问题。我习惯把Samples per Symbol设成10,这样每个符号只画一个点;如果你不设置,默认每个采样都画,星座图上全是点与点之间的过渡轨迹,看起来就像一坨混乱的云。想看眼图风格的过渡线时再临时关掉符号采样。
判定QPSK点簇合格的标准,我总结了三条:
- 能看到四个彼此分离的簇,而不是一个圆环或一团云;
- 每个簇的形状接近圆形,而不是拖着长长的尾巴或旋转成弧;
- 簇半径相对簇间距离足够小,目测不会发生误判。
任何一条不满足,都说明链路里有一个具体环节出了问题,排查方向在第5章展开。
4.4 90度相位模糊:一个绕不开的坑
当你第一次看到完美的四个点簇并且锁得很稳,还没来得及高兴,可能会发现解调出的比特和发送端完全对不上——好像整体旋转了一个象限。这就是Costas环的90度相位模糊。GNU Radio自带的Costas环模块有一个相位模糊处理选项,但QPSK本质上是四相调制,任意旋转90度都落在合法星座点上,环路无法区分。
工程上最常用的解法是差分编码:发送端把绝对相位换成相邻符号的相位差来编码,接收端比对相邻符号的相位变化而非绝对相位。GNU Radio的DQPSK解调器就是这么干的。我这次实验为了保留“观察四点簇”的直观性,用了绝对QPSK加一个已知PN序列做相位估计,在离线数据处理里把旋转纠正回来。严格讲这是一条偷懒路径,但它适合教学场景——让你在星座图上直观看到QPSK的本质。
如果只想要一个“能跑通且不出错”的演示,直接用DQPSK更省心。接受少量噪声代价,换来绝对相位无关,对刚上手的项目来说是很划算的取舍。
4.5 想做BER测试?一个Python脚本就够了
星座图只能看趋势,要量化链路质量还得算误码率。简单做法是发射端和接收端各自把符号流存成文件,在Python里对齐后比对。下面是简化版的比对脚本思路:
import numpy as np tx_syms = np.load('tx_symbols.npy') # 发射端符号序列 rx_syms = np.load('rx_symbols.npy') # 接收端判决后的符号序列 # 去掉延迟和保护段,粗略对齐 n = min(len(tx_syms), len(rx_syms)) - 100 tx = tx_syms[100:100+n] rx = rx_syms[100:100+n] errors = np.sum(tx != rx) ber = errors / n print(f'符号错误数: {errors}, 误符号率: {ber:.6f}')真正做BER实验时还有个细节:接收端判决前要让发送端连续发固定数量的随机比特,并在数据里插入帧头和长度字段;否则离线对齐时会因为一两个符号的偏移导致错误率飙升。
4.6 先别上Costas环:接收端的“裸奔”调试法
我的调试习惯是分阶段往接收链路里加同步模块。第一次搭接收流图,先不加定时同步和Costas环,直接在Constellation Sink上看原始采样点。这时候你会看到一堆乱跑的点或者旋转的轨迹——不要慌,这是正常的。
然后逐步打开:先开匹配滤波,点会略聚拢;再开定时同步,点会聚成四个条带;最后开Costas环,条带锁定成四个点簇。每加一级就停下来观察变化,而不是把所有模块全堆上去之后才看结果。这样做的好处是,一旦点簇不收敛,你能马上判断是哪一级没工作。
5. 实测问题排查链路:星座图不漂亮时,按顺序查
到了这一步,你已经有了完整的收发链路。接下来是实验最有价值的阶段:星座图出各种幺蛾子,然后你一行一行找到原因。下面是我在P201Pro上实测时反复遇到的四类问题,按出现频率排序。
5.1 星座图整体转圈,形成一条环形轨迹
这是最经典的QPSK接收故障。现象:四个点簇看不见,取而代之的是由离散点连成的一个圆环,旋转速度还比较均匀。根因几乎都是载波频偏没有被消除:Costas环没锁定,或频偏超出了它的捕获范围。
排查链路是这样的:
- 先确认是从发射到接收的全程链路都正常,换用射频线缆自环测试排除空间信道干扰;
- 看频谱,用Freq Sink观察接收信号的中心频率是否精确落在预设频率上,偏差大就证明频偏存在;
- 如果频偏大于Costas环的捕获范围,在流图最前面加Frequency Xlating FIR Filter,手动设置一个负频偏,把信号拉回零频;
- 检查两块板卡是否共参考时钟,不共源时先外接10MHz共源,从源头消灭大部分频偏。
Costas环的Loop Bandwidth也要检查。太大了环路噪声大,点簇抖;太小了锁不住快频偏。我一般从0.02起步,视情况在0.005到0.05之间调节。
5.2 点簇之间全是轨迹线,四个点聚不拢
现象:星座图能看到四个方向上有“密度堆积”,但点与点之间布满连线的轨迹,整体看起来像风车或十字形。根因九成是符号定时同步没有生效,导致采样点落在符号跳变沿上,而不是符号稳定区。
排查方向:
- 确认Polyphase Clock Sync或Symbol Sync的Samples per Symbol参数和实际采样率一致,不一致时模块按错误的速率插值,点自然散;
- 确认RRC匹配滤波器的滚降系数和发射端一致,α不匹配会让符号波形失真;
- 检查定时同步的环路带宽,太窄会锁定很慢,观察时间不够时会误以为没工作;
- 最简单的一种情况:Constellation Sink没设Samples per Symbol,所有采样点都画出来,过渡轨迹当然全在。先检查这个,能省半小时。
5.3 点簇明显但边缘毛刺粗、外圈扩散
现象:四个点簇能分辨,但每个簇的轮廓不是规则的圆,而是带一圈毛刺,甚至向远离原点的方向拖出尾巴。这通常是射频链路非线性或者增益过大的表现。
排查链路:
- 先降低接收端RX增益,P201Pro的RX增益从30dB往下调,观察毛刺是否减少。如果少了,说明接收链路进入饱和区,信号超出ADC满量程,削顶失真;
- 再降低发射端TX增益(增大衰减),排除发射功放非线性;
- 检查天线是否贴得太近,两个天线距离小于半米时,发射信号可能把接收前端直接“堵”到饱和,加20dB衰减或拉远距离再试;
- 还有一个容易被忽略的:供电电压不稳或USB供电不足时,板卡增益会漂,点簇边缘也会散。换独立电源再观察。
把“增益往低调”这条放在第一位,是因为新手实验最容易犯的错就是觉得增益越大信号越好。实际上SDR接收链路的最佳增益点,永远在“足够大”和“不过载”之间。
5.4 点簇一开始正常,几分钟后慢慢漂移散开
现象:刚锁定星座图很漂亮,放着不动,十几分钟后点簇缓慢旋转或扩散。原因主要是热漂移和本振失锁。AD9361的本振频率由PLL产生,温度变化会导致频率缓慢漂移,两块板卡各自漂移的方向还不一致。
处理办法:
- 让板卡上电预热10分钟再开始实验,多数漂移会在预热后明显减小;
- 检查PLL锁定状态,P201Pro的驱动日志里通常有锁相指示;如果不锁定,检查参考时钟的连接和电平;
- 不共源时给接收端加更大幅度范围的粗频偏校正,让Costas环持续能拉回来;
- 如果漂移严重到同步环跟不上,降低符号速率或缩短单次观测时间,用“短突发”方式做实验。
这四类问题占了我实验调试时间的八成。你可以发现,排查套路高度一致:先回到自环排除信道,再逐级检查基带和射频参数,最后考虑硬件层面的时钟和热稳定性。不需要依赖高端仪器,星座图本身就是最好的示波器。
动手做这个实验时,我最大的体会是:不要追求一次把所有模块接对。先把发射端流图完成,用频谱仪或Freq Sink确认信号带宽和中心频率符合预期;再把接收端流图只接匹配滤波和星座图,不做任何同步,观察原始点的运动轨迹;最后一级一级加入同步模块。每加一级,都停下来确认现象是否符合预期。
这套流程下来,你对Costas环、定时同步、脉冲成型这些概念的理解,会比看十遍教材都深刻。下一步可以沿着同样的链路去推BPSK、16QAM甚至OFDM——星座图变成4个点只是起点。