ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

数字带通传输工程实践:调制解调、同步判决与实测避坑

数字带通传输工程实践:调制解调、同步判决与实测避坑

数字带通传输这个题目,乍一听像是教科书目录里的一个章节名,但凡是真正做过调制解调链路的人都知道,它其实是整条通信链路里最容易"翻车"的一段。基带那一套东西——成型滤波、眼图、判决——在实验室里跑得好好的,一旦把信号搬到载波上,通过一个真实的射频通道再回到接收端,星座点就开始发散,误码率曲线跟理论值差出两个数量级,锁相环时不时失锁。我带过几个做数字通信的工程小组,几乎每一批新人在第一次调试带通系统时,都会经历同样的困惑:明明代码是照着公式写的,为什么实测就是不行。

这篇内容想聊的就是这件事。数字带通传输,说白了就是把数字比特流变成适合在带通信道上传输的射频信号,再在接收端把它还原回比特——调制、解调、同步、判决这一整套。它适合两类人看:一类是通信、电子相关专业正在学这门课、但被公式绕晕的同学,另一类是已经上手做软件无线电、数字收发机、无线数传模块,却总在实测环节卡住的工程师。我会从"为什么非得搬到载波上"讲起,把几种主流调制方式的取舍逻辑掰开揉碎,再重点讲接收端那些教科书上讲得轻描淡写、实际调试中却要命的问题。

1. 带通传输存在的理由:基带信号为什么不能直接上天线

1.1 基带传输的天花板卡在哪儿

先从最朴素的问题开始:我们已经有基带传输了,为什么还要多此一举做带通?很多教材一上来就给结论"因为信道是带通的",这个回答没错,但太抽象,理解不了就记不住。

你可以把基带信号想象成一段包含很低频率成分的波形,方波、NRZ码流这些东西,能量集中在零频附近一直延伸到某个截止频率。这种信号有个特点:它含有直流分量和极低频分量。而天线这个东西的物理特性决定了,它的辐射效率跟尺寸和波长的比值强相关,要在有限的物理尺寸上把能量有效地辐射出去,信号的中心频率必须足够高。一段几十兆赫兹带宽、中心在零频的基带信号,你几乎没办法给它设计一个有效辐射的天线——要么天线大得离谱,要么辐射效率低到可以忽略。

另一个更现实的原因是频谱管理。空中的频谱是被划分好的,每一类业务都只能在指定的频段里工作。基带信号一屁股坐在零频上,跟谁都抢位置,这不是技术问题,是规则问题。所以必须把信号的频谱"搬"到分配的频段上去,这个过程就是调制。

还有一个常被忽略的点:多路复用。把不同基带信号搬到不同的载波频率上,就可以在同一个物理介质里同时传多路信号,频分复用就是这么来的。

一个常见的误解:很多人以为调制是为了"抗干扰"。严格来说,调制本身并不增加信号的能量,也不直接提升抗噪能力,它解决的是"能不能发出去"和"发到哪里"的问题。抗噪能力是调制方式和接收机结构共同决定的,是另一个维度的事。

1.2 频谱搬移这一步,本质是乘一个正弦载波

调制的数学本质非常干净:把基带信号 s(t) 乘上一个高频正弦载波 cos(2πf_c t),频谱就被搬到了 ±f_c 附近。这里有个关键细节值得说清楚——实信号乘载波之后,频谱是双边对称地搬到正负两个频率上的,正频部分和负频部分互为镜像,携带的是同一份信息。这就意味着有一半的频谱资源被"浪费"在镜像上了。

真正在工程里干活的方式是复基带表示:把信号拆成 I、Q 两路,分别乘 cos 和 -sin,然后相加。这样处理的好处是,整个链路的分析、仿真、实现都可以在复基带域完成,采样率可以降到带宽量级而不是载频量级,计算量差好几个数量级。实际做软件无线电的人基本都是这么干的:ADC 在中频采样,数字下变频到零中频,之后所有的解调、滤波、同步都在复基带上跑,最后才判决出比特。

这里插一句实操经验。我第一次做数字上变频的时候,直接把复基带信号乘上 cos(2πf_c n) 就往外送,结果频谱分析仪上看到的是一团糊,镜像分量和有用信号叠在一起。问题就出在没做正交上变频——复信号乘单一实载波,正负频率成分会重叠。正确做法是 I 路乘 cos、Q 路乘 sin 再相减,或者干脆用数字上变频芯片内部的复数混频器。这个坑非常经典,仿真里因为直接处理复数看不出来,一上硬件就现原形。

带通传输的性能衡量,本质上就三个指标在互相拉扯:频带利用率(每赫兹带宽能传多少比特每秒)、功率效率(达到某个误码率需要多少每比特能量)、实现复杂度。任何一个调制方案的设计,都是在这三者之间找平衡点,没有哪个方案能三项全占。理解了这一点,后面所有的比较就有了主线。

2. 四种二进制调制:波形很相似,工程难度差得远

2.1 2ASK:最接近模拟电路思路的数字调制

2ASK 就是幅移键控,用载波的有无或者幅度高低来表示 0 和 1,最典型的形态就是 OOK(通断键控)。它的实现简单到有点粗暴:一个乘法器加一个门控就完事了。早期的无线电报、红外遥控、一些低成本的 RFID 标签,用的都是这个思路。

它的优点和缺点几乎是同一个东西:简单。简单意味着成本低、功耗小、对相位不敏感,接收端用包络检波就能解调,连相干载波都不需要恢复。但简单也意味着抗噪能力弱——判决完全依赖幅度,任何信道衰落、多径引起的幅度起伏都会直接translate成误判。2ASK 在加性高斯白噪声信道下的相干解调误码率,用 Q 函数写出来跟 2PSK 差了 3 dB 左右(同样的每比特能量,2ASK 需要多一倍的能量才能达到相同误码率),而实际信道里还有衰落,这个差距只会更大。

我做无线数传模块的时候有过一个教训:某款低成本遥控方案用 OOK,标称距离一百多米,实际在室内环境里二十米就开始误码。原因很简单,室内多径让幅度剧烈起伏,包络检波的门限设死之后根本扛不住。后来换成 2FSK,同样的发射功率,稳定性立刻上了一个台阶。如果你的应用场景里信道有衰落、有遮挡、有移动,2ASK 基本可以直接排除。

2.2 2FSK:用频率间隔换来的稳健性

2FSK 用两个不同的频率分别代表 0 和 1。它最大的价值在于:判决依据是频率而不是幅度或绝对相位,所以对幅度起伏和相位旋转都不敏感。包络检波加上两个中心频率的带通滤波器就能解调,非相干检测的误码率虽然比相干差一些,但胜在接收机极其简单,而且不需要载波恢复——对低成本、低功耗的无线模块来说,这个特性太香了。

但代价也很明显:频带利用率低。两个频率之间要拉开足够的间隔才能保证正交性,这个间隔在相干检测下最小是 1/(2T)(T 是符号周期),非相干检测下要 1/T。换算成带宽,2FSK 占用的频谱通常是 2ASK 的 2 到 3 倍。在频谱资源紧张的应用里,这是个硬伤。

调试 2FSK 有个容易被忽略的细节:两个频率的正交性。理论上的调制指数 h = 2Δf·T,h=0.5 的 MSK 是最紧凑的正交方案,h=1 的 CPFSK 则更宽松。如果 h 取在非整数位置,两个频率上的信号在符号周期内不严格正交,解调时就会产生交叉干扰。我用 FPGA 做 2FSK 调制器的时候,第一次把 h 取成 0.7,眼图张开度明显不如 h=0.5 和 h=1 的情况,查了半天才发现是正交性问题。h 要么取 0.5,要么取大于等于 1 的整数,别拍脑袋取中间值。

2.3 2PSK 与 2DPSK:相位携带信息的甜与苦

2PSK 用载波的 0 和 π 两个相位表示比特,这是二进制调制里功率效率最高的方案。在相同的每比特能量下,2PSK 的误码率是所有二进制方案里最低的,比 2ASK 好 3 dB,比非相干 2FSK 好得更多。原因不难理解:0 和 π 两个相位在星座图上距离最远,判决的容限最大。

但 2PSK 有个绕不开的麻烦——相位模糊。接收端要相干解调,必须恢复出一个与发送端同频同相的载波。问题是,很多载波恢复电路(比如平方环、Costas 环)在锁定的时候,有可能锁在 π 的相位上,因为 2PSK 的信号本身在相位旋转 π 之后看起来是一样的。结果就是解调出来的比特全部翻转,出现"倒 π"现象。这个错误极其隐蔽,因为翻转后的数据流在统计特性上完全正常,只是内容全反了。

差分编码就是来解决这个问题的。2DPSK 不直接用相位表示比特,而是用"相位的变化"表示比特:当前符号和前一符号相位相同代表 0,相差 π 代表 1。这样即使出现倒 π,前后符号的相对关系不变,差分译码之后数据依然正确。代价是误码率会略有恶化,因为一个符号的错误会影响两个比特的判决,非相干差分检测的误码率约为 0.5·exp(-Eb/N0),比相干 2PSK 差 2 到 3 dB。

实际工程里一个非常实用的做法:不管用什么调制,帧头都放一段已知的同步序列。接收端靠这段序列不仅能做帧同步,还能顺便判断有没有出现相位翻转,如果检测到翻转,直接把后续数据取反或者把解调器的参考相位纠正过来。这比纯靠差分编码更灵活,代价只是几个字节的开销。

2.4 二进制调制的横向对比:一张表值一千句话

把四种方案的性能摆在一起看,取舍关系会清晰很多。下表的误码率公式中,Eb 是每比特能量,N0 是单边噪声功率谱密度,Q(·) 是高斯 Q 函数。

调制方式解调方式误码率近似相对 2PSK 的功率代价带宽(α 为滚降系数)主要工程痛点
2ASK相干Q(√(Eb/N0))约 3 dB(1+α)Rb对幅度衰落极敏感
2ASK包络检波0.5·exp(-Eb/(4N0))约 6 dB 以上(1+α)Rb门限随信道变化
2FSK相干Q(√(Eb/N0))约 3 dB约 (3~4)Rb正交性依赖频率间隔
2FSK非相干0.5·exp(-Eb/(2N0))约 4 dB约 (3~4)Rb频带利用率低
2PSK相干Q(√(2Eb/N0))基准 0 dB(1+α)Rb相位模糊
2DPSK差分相干0.5·exp(-Eb/N0)约 2.5 dB(1+α)Rb差分译码带来误码扩散

看这张表的时候要注意,理论上限摆在那儿,但工程选型从来不是只看误码率。一个远距离低速的工业遥控器,用非相干 2FSK,误码率差几个 dB 完全能接受,因为它省掉了载波恢复电路,成本和功耗下降一大截,可靠性反而更好。反过来,一个卫星通信链路,每一 dB 的功率都要精打细算,那就必须上相干 2PSK 甚至更高效的方案,然后把同步电路做扎实。性能表是决策的起点,不是终点。

3. 多进制调制:把每个符号的比特数榨上去

3.1 QPSK:两个正交载波各干一份活

QPSK 是二进制往多进制过渡时最自然的一步:用两个互相正交的载波(cos 和 sin)各自传一路 2PSK,合起来每个符号携带 2 个比特。星座图上是四个点,分布在 0、π/2、π、3π/2 四个相位上。

它的妙处在于:在同样的带宽下,比特率翻倍,而每比特的功率效率和误码率性能跟 2PSK 基本持平。这不是天上掉馅饼,是因为那两个载波是正交的,在同一个符号周期内互不干扰,接收端可以把它们分离出来单独判决。从信息论角度看,这相当于把二维信号空间利用起来了,而 2PSK 只用了一维。所以 QPSK 几乎是所有数字通信系统里最常见的调制方式之一,从卫星到 4G 到各种数传电台,到处都是。

QPSK 的误码率在格雷映射下,符号错误率与比特错误率近似相等,表达式是 Q(√(2Eb/N0)),与 2PSK 相同。这里的"格雷映射"是关键:相邻的星座点只差一个比特,这样即使判决到了邻近点,也只错一个比特。如果映射做错,一个符号错了可能错两个比特,误码率直接翻倍。

星座映射这件事看着简单,实际是个大坑。我曾经在一个项目里接手别人的代码,发现误码率曲线在低信噪比下比理论值高一倍,查了很久,最后是发现星座点映射没用格雷码——发送端和接收端用的映射表还不一致,等于凭空多了一倍错误。映射表一定要单独做成一张常量表,收发两端引用同一份源码,别各写各的。

3.2 OQPSK 与 π/4-QPSK:为包络起伏打的补丁

QPSK 有个隐藏问题:当星座点从 (1,1) 跳到 (-1,-1),I 和 Q 两路同时翻转,合成信号的包络会瞬间过零。经过非线性放大器(比如工作在饱和区的功放)之后,这种过零会被削掉,频谱重新长出来,产生带外辐射,干扰邻道。

OQPSK 的解法很巧妙:把 Q 路的符号错开半个符号周期,这样 I 和 Q 的跳变永远不同时发生,包络最大只降到原值的 1/√2,不会过零。代价是需要在接收端把两路的定时关系对齐,实现上略微麻烦。π/4-QPSK 走的是另一条路:让星座点在两个旋转了 45° 的 QPSK 星座图之间交替跳变,同样避免了过零,而且因为它每符号的相位跳变限制在 ±45° 和 ±135°,可以用差分检测,接收机可以做得更简单。这两种方案在早期的蜂窝系统和专用移动通信里用得挺多。

3.3 16QAM 及更高阶:密度换带宽的买卖

16QAM 把星座点扩到 16 个,每个符号带 4 比特,频带利用率是 QPSK 的两倍。星座点不再是均匀分布在圆周上,而是排成 4×4 的方阵。点之间的距离变小了,判决容限变小,所以同样的平均功率下误码率会明显变差。

近似公式是 BER ≈ (3/8)·erfc(√(0.4·Eb/N0)),粗略地说,同样误码率下 16QAM 比 QPSK 多需要 4 到 6 dB 的信噪比。这 4 到 6 dB 换来的是带宽减半,值不值就看你的系统是功率受限还是带宽受限。卫星通信通常功率受限,倾向于低阶调制;地面微波接力、有线同轴这类带宽紧张的场景,就愿意上高阶。

再往上走,64QAM、256QAM 的规律是一样的:每增加 4 倍星座点数,约多 6 dB 功率代价换一倍带宽收益。到了 1024QAM 这种量级,对信噪比、相位噪声、IQ 不平衡的要求已经苛刻到近乎变态——相位噪声哪怕只有零点几度,星座图都会糊掉。所以高阶调制从来不是"算法写对了就行",整个射频前端的指标都得跟上。

调制方式每符号比特理论 Eb/N0(BER=1e-6)频带利用率(α=0.35)典型应用倾向
2PSK1约 10.5 dB约 0.74 bps/Hz功率受限、低速
QPSK2约 10.5 dB约 1.48 bps/Hz通用、卫星、数传
16QAM4约 14.5 dB约 2.96 bps/Hz带宽受限、视距链路
64QAM6约 18.5 dB约 4.44 bps/Hz高信噪比固定链路

(表中 Eb/N0 为含编码前的粗略参考值,实际系统算上编码增益会低不少,这里只用于横向比较量级。)

3.4 用 Python 把星座图和误码率曲线跑出来

光看公式容易麻木,自己跑一遍曲线会建立直觉。下面这段代码把 QPSK 和 16QAM 的误码率仿真和星座图都做出来了,可以直接在本地跑:

import numpy as np import matplotlib.pyplot as plt from scipy.special import erfc def qfunc(x): return 0.5 * erfc(x / np.sqrt(2)) def simulate_qpsk(ebn0_db, n_sym=200000, seed=1): rng = np.random.default_rng(seed) ebn0 = 10 ** (ebn0_db / 10.0) # 每比特能量归一化为1,QPSK每符号2比特,符号能量为2 noise_var = 1.0 / (2 * ebn0) # 每维噪声方差 bits = rng.integers(0, 2, n_sym * 2) syms = ((1 - 2 * bits[0::2]) + 1j * (1 - 2 * bits[1::2])) / np.sqrt(2) noise = (rng.normal(0, np.sqrt(noise_var), n_sym) + 1j * rng.normal(0, np.sqrt(noise_var), n_sym)) rx = syms + noise dec_i = (rx.real > 0).astype(int) dec_q = (rx.imag > 0).astype(int) err_i = np.sum(dec_i != bits[0::2]) err_q = np.sum(dec_q != bits[1::2]) return (err_i + err_q) / (n_sym * 2), rx def simulate_16qam(ebn0_db, n_sym=200000, seed=2): rng = np.random.default_rng(seed) ebn0 = 10 ** (ebn0_db / 10.0) levels = np.array([-3, -1, 1, 3]) # 16QAM平均符号能量为10,每维5,每比特2.5 noise_var = 2.5 / (2 * ebn0) idx_i = rng.integers(0, 4, n_sym) idx_q = rng.integers(0, 4, n_sym) syms = (levels[idx_i] + 1j * levels[idx_q]) / np.sqrt(10) noise = (rng.normal(0, np.sqrt(noise_var), n_sym) + 1j * rng.normal(0, np.sqrt(noise_var), n_sym)) rx = syms + noise # 简单硬判决:就近取电平 dec_i = np.argmin(np.abs(rx.real[:, None] - levels / np.sqrt(10)), axis=1) dec_q = np.argmin(np.abs(rx.imag[:, None] - levels / np.sqrt(10)), axis=1) # 格雷码比较:这里只统计符号级错误,用于观察趋势 sym_err = np.sum((dec_i != idx_i) | (dec_q != idx_q)) return sym_err / n_sym, rx ebn0_list = np.arange(0, 15, 1) ber_qpsk, ber_16qam = [], [] for e in ebn0_list: b, _ = simulate_qpsk(e) ber_qpsk.append(max(b, 1e-6)) s, _ = simulate_16qam(e) ber_16qam.append(max(s, 1e-6)) plt.figure(figsize=(8, 5)) plt.semilogy(ebn0_list, ber_qpsk, 'o-', label='QPSK BER') plt.semilogy(ebn0_list, ber_16qam, 's-', label='16QAM SER') plt.grid(True, which='both') plt.xlabel('Eb/N0 (dB)') plt.ylabel('Error Rate') plt.legend() plt.title('QPSK vs 16QAM Error Performance') plt.show() _, rx_qpsk = simulate_qpsk(10) _, rx_16qam = simulate_16qam(16) fig, ax = plt.subplots(1, 2, figsize=(10, 5)) ax[0].plot(rx_qpsk.real, rx_qpsk.imag, '.', ms=1, alpha=0.3) ax[0].set_title('QPSK @ 10 dB') ax[1].plot(rx_16qam.real, rx_16qam.imag, '.', ms=1, alpha=0.3) ax[1].set_title('16QAM @ 16 dB') for a in ax: a.grid(True) a.set_aspect('equal') plt.show()

跑完你大概会看到两个直观现象:第一,QPSK 在 9 到 10 dB 附近误码率就掉到 1e-5 量级,而 16QAM 要差不多 15 dB 才到同样的水平,差的那 5 到 6 dB 就是前面说的功率代价;第二,16QAM 星座图上,外围点和内圈点的散射程度不一样,靠近原点的点看起来更"糊"——这不是错觉,是因为判决区域小,同样的噪声下更容易跨区。看懂这两点,比背公式有用得多。

4. 接收端才是真正的战场:同步、匹配滤波与判决

4.1 载波同步:Costas 环能锁上,但锁对是另一回事

发送端调制简单,接收端恢复载波才是数字带通传输的核心难点。为什么难?因为接收到的信号里根本没有一个独立的载波分量可以提取——2PSK 和 QPSK 的已调信号在载频上功率为零(抑制载波调制),你必须从信号的相位变化里"猜"出载波。

平方环是最直观的做法:把信号平方,2PSK 的 ±1 相位被平方成统一相位,频谱中就会出现 2f_c 的离散分量,提取出来二分频就得到载波。听起来完美,实践中有两个坑:一是平方操作会让噪声也翻倍,低信噪比下环路信噪比很差;二是二分频电路的初始状态不确定,锁在 f_c 还是 f_c+π 是随机的,这就是前面说的相位模糊的根源。

Costas 环是更常用的方案,本质是一个负反馈环路,用 I、Q 两路的乘积作为鉴相误差,把 Q 路压到零。它不需要平方,噪声性能更好,但同样的相位模糊问题依然存在——环路可能稳定在四个相位中的任意一个(QPSK 情况下)。

实际工程里的处理办法通常是组合拳:用 Costas 环做载波跟踪,配合帧头的独特码(UW)做绝对相位判定,一旦识别出当前锁定的是哪个相位,就在后续解调中做相应的旋转补偿。这个流程在软件无线电里非常容易实现,因为旋转就是一个复数乘法,没有任何硬件代价。

另外要注意环路的参数选择。环路带宽太窄,跟踪慢,遇到频偏大的场景会失锁;带宽太宽,噪声抑制差,相位抖动大,高阶调制根本扛不住。常见经验是:环路带宽取符号率的 0.5% 到 2%,具体看频偏范围和相位噪声水平。我用 16QAM 做测试的时候,环路带宽取到 1% 都嫌宽,星座图明显发散,收到 0.3% 才干净。先估算你的晶振频偏和相位噪声,再倒推环路带宽,别直接抄别人的参数。

4.2 位同步与根升余弦滤波:滚降系数不是随便定的

位同步(定时恢复)解决的是"什么时候采样"的问题。采样点落在眼图张开最大的位置,误码率才最低。Gardner 算法是最常用的非数据辅助定时恢复方法,每个符号只要两个采样点,用前后两段的能量差来估计定时误差,实现简单,对频偏有一定容忍度。

这里有个和成型滤波强相关的问题:发送端用什么滤波器成型,接收端就必须用什么滤波器匹配。数字通信里最常用的是根升余弦(RRC)滤波器,收发各放一个,级联起来构成一个完整的升余弦响应,满足无码间干扰的奈奎斯特准则。如果发送端用了 RRC 而接收端只是简单的低通,整个链路的响应就不满足无 ISI 条件,眼图闭合,误码率地板直接被你抬起来。

滚降系数 α 的选择是个典型的权衡:

  • α 越小,频谱越紧凑,频带利用率越高,但时域拖尾越长,对定时误差越敏感。α 趋近 0 时理论上带宽等于符号率,但时域响应会拖到几十个符号长,一旦定时有偏差,ISI 立刻爆发。
  • α 越大,时域响应越短,对定时误差宽容,但占用带宽越大。

实际系统里 α 一般取 0.2 到 0.35。α=0.35 是卫星通信里非常经典的值,兼顾了带宽和鲁棒性;α=0.22 在某些地面系统里也常见。我做过一个带宽非常紧张的链路,被迫用到 α=0.15,结果定时恢复环路的捕获范围窄得可怜,接收机必须先把频偏校准到 ±0.1 ppm 以内才可能锁定——这就是小滚降带来的代价。

滤波器长度也别抠门。RRC 滤波器的截断长度一般取 6 到 12 个符号周期(每边 3 到 6 个),太短会让频域响应出现明显纹波,带外抑制变差。我在资源受限的 FPGA 上试过 4 个符号长度的截断,频谱仪上一眼就能看到旁瓣翘起来了,邻道泄漏超标。

4.3 判决门限、AGC 与 EVM:三个必须现场调的指标

理论上的判决门限是中点(比如 BPSK 是 0),实际系统里这个门限必须动态调整,因为信号经过信道之后幅度会漂。AGC(自动增益控制)就是干这个的,它把信号电平拉到一个固定参考值附近,这样判决门限和后续的软判决尺度都能稳定下来。

AGC 的收敛速度是个矛盾点:太快会把信号的包络起伏(本来就是信息的一部分)当成增益变化给抹掉,太慢又跟不上信道衰落。做法通常是在帧头用一段已知幅度的序列做快速粗调,进入数据段之后切成慢速跟踪。这个套路在几乎所有实用接收机里都能见到。

EVM(误差矢量幅度)是衡量带通传输质量最直观的指标,定义是实际星座点与理想点之间的误差矢量 RMS 值,除以理想点的平均幅度,用百分比或 dB 表示。它把 IQ 不平衡、相位噪声、非线性失真、滤波器失配这些问题全部打包成一个数字。实测中,一个设计良好的 QPSK 链路 EVM 应该能做到 5% 以下,16QAM 要求更严,通常压在 3% 以内。如果你的 EVM 一直下不去,可以按这个顺序排查:先看星座图中心有没有偏移(直流偏置)、再看四个象限是不是缩放不一致(IQ 增益不平衡)、再看点云是不是旋转的(相位噪声或频偏未收敛)、最后看外围点是不是被压扁(功放非线性)。

现象最可能的原因排查手段
星座图整体偏移原点IQ 直流偏置关闭信号看基带输出的直流分量
四个象限幅度不一致IQ 两路增益失配注入单音测两路幅度响应
点云呈弧形拖尾残余频偏未收敛看相位误差随时间的变化曲线
外围星座点被压向圆心功放饱和压缩降低输入功率看 EVM 是否改善
所有点都糊成一团定时未锁定或滤波失配看眼图张开度、检查 RRC 系数

5. 从仿真到实测:几个必须提前知道的坑

5.1 带外辐射与频谱模板:别等测试报告打回来才想起这事

仿真里我们通常只关心解调性能,很少去看发射频谱的边缘。但实际产品要过频谱模板测试,带外辐射超标是极常见的退回原因。根源一般是两个:成型滤波器的阻带抑制不够,或者功放的非线性把频谱重新"长"了出来。

前者的解决办法是加长滤波器、提高阶数,或者在 RRC 之后再跟一级低通做补充抑制。后者更麻烦,属于非线性问题,只能靠回退功率(back-off)或者做预失真。我遇到过一个案子,调制方式和滤波器都没问题,频谱仪上一看,邻道泄漏比要求高了 6 dB,最后是把功放的工作点从饱和区往回退了 4 dB 才解决——代价是输出功率下降,覆盖距离缩短,整个链路预算要重算。这类问题一定要在方案阶段就评估,别等硬件定型了才发现没余量。

5.2 IQ 不平衡与直流偏置:零中频架构的固有麻烦

零中频(直接变频)架构省掉了中频滤波器,成本低、集成度高,但它有两个天生的毛病:IQ 两路的增益和相位不可能完全一致,本振泄漏会在零频产生一个直流分量。这两个问题在星座图上的表现前面表格里已经列了,处理办法也相对成熟:直流可以在数字域用高通或者均值相减去掉,IQ 不平衡可以用一个 2×2 的补偿矩阵校正,矩阵参数通过注入测试信号或者盲估计得到。

这里有个实操细节值得说:直流消除的高通滤波器截止频率不能设太高,否则会把信号本身的低频成分也削掉,导致星座图整体变形。一般截止频率取符号率的万分之一到千分之一量级就够了,只去掉缓慢漂移的那部分。

5.3 仿真和实测对不上,八成是这三件事

很多人跑完 Monte Carlo 仿真,曲线漂亮得跟理论值重合,一上硬件发现差了两三个数量级。按我的经验,八成是下面三件事之一:

第一,信噪比的标定口径不对。仿真里 Eb/N0 是按符号能量和噪声方差直接算的,实测里你测的是射频口的功率,中间隔着滤波器插损、放大器增益、ADC 的满量程折算,任何一个环节算错 3 dB,曲线就平移一大截。建议在链路里插一个已知功率的校准音,从头到尾把增益链算清楚。

第二,噪声不是白噪声。仿真默认 AWGN,实际信道里有相位噪声、杂散、邻道干扰,这些非高斯成分对高阶调制的影响远大于高斯噪声。尤其是相位噪声,它会让星座点沿圆周方向扩散,16QAM 这种对相位敏感的调制直接就废了。评估相位噪声的影响,可以在仿真里给每个符号乘一个随机相偏,这是很实用的近似手段。

第三,同步环路的瞬态被忽略了。仿真常常假设从第一个符号开始就完美同步,实测里环路要几百个符号才能收敛,这段时间的数据全是错的。所以帧结构里必须有前导序列,而且要按最坏情况下的捕获时间来设计长度。这个长度不够,表现出来就是"误码率随帧长变化",短帧全对,长帧反而错——这其实是前导不够、环路没锁稳的信号。

最后分享一个小技巧:调试带通链路的时候,别一上来就盯着误码率看,那是个滞后指标,出了问题也不知道从哪下手。先把星座图、眼图、频谱这三张图同时抓出来看,星座图看幅度和相位,眼图看定时和 ISI,频谱看带外和杂散,三张图一对照,问题范围基本就缩小到一两个模块了。这个习惯我保持了十几年,比任何自动化诊断工具都好使。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进