毕业设计或者课程设计里做到“Turbo码 + 调制方式”这类题目的人很多,但真正把Turbo码和GMSK放在一条链路上跑通、再给出可复现Matlab代码的资料,确实不算多。BPSK和Turbo码的组合门槛低、结果直观,GMSK就麻烦不少——它本质上是带记忆的连续相位调制,匹配解调要在相位树里做最大似然序列估计,复杂度直接上了一个台阶。这篇文章就围绕一个很经典的做法展开:发射端用Turbo码做信道编码,调制端分别在BPSK和GMSK两条链路上发送,接收端对GMSK用二比特差分解调提取软信息,再交给log-MAP迭代译码器。整个方案用Matlab实现,既能快速复现误码率曲线,又能比较两种调制方式在编码增益上的差异。
我最近把这条链路完整拉了一遍,从相位成形到差分解调、再到Turbo译码的软信息对接,踩了不少坑。下面按工程实现的顺序,把每一步的设计思路、Matlab实现细节和实测中要注意的点都写出来。
1. 链路怎么搭:把Turbo码与两种调制方式揉进同一条仿真管线
先看整体结构。既然要对比turbo+BPSK和turbo+GMSK,就不应该各自写一套互不相关的代码。正确做法是搭一条统一管线:Turbo编码器输出编码比特,经过相同的随机交织和码率匹配后,进入调制模块;调制模块做成可切换的,BPSK直接符号映射,GMSK走相位成形;接收端根据调制方式选择对应的解调器,输出软比特LLR,送到同一个Turbo迭代译码器。
这个设计的好处很明显——编码增益的差异完全由调制和解调方式决定,排除了其他变量。链路各模块的职责划分见下表。
| 模块 | 实现要点 | 输出 |
|---|---|---|
| Turbo编码器 | 两个RSC分量码 + 随机交织器,可配置码率1/2或1/3 | 编码比特流 |
| 信道交织/随机化 | 打散突发错误,与Turbo内交织区分 | 交织后比特流 |
| BPSK调制 | 0/1映射为±1,归一化符号能量 | 基带符号序列 |
| GMSK/MSK调制 | 高斯滤波 + 相位积分,恒定包络 | 复数基带波形 |
| AWGN信道 | 按Eb/N0折算噪声方差 | 接收波形 |
| 二比特差分解调 | 延迟2T共轭相乘,计算软量 | 每符号软比特 |
| Turbo迭代译码 | Max-Log-MAP,迭代8次 | 信息比特硬判决 |
仿真时我建议先把BPSK链路跑通,把Turbo译码器验证无误后,再切换到GMSK链路。这样排错范围清晰:GMSK链路出问题,问题几乎一定出在调制或差分解调侧,而不是Turbo译码器本身。
一个容易被忽略的细节是编码后比特与调制符号的映射关系。Turbo码内部交织器的索引、以及交织后比特进入调制器的顺序,都会影响差分解调性能。GMSK本身具有相位记忆,相邻比特的相位增量互相影响,如果交织器设计不合理,会把这种记忆性打散,导致差分解调的软信息质量下降。实测中普通随机交织基本够用,交织深度取信息块长度量级即可。
2. MSK与GMSK的相位成形逻辑:从相位树到高斯脉冲限带
MSK和GMSK经常放在一起讲,因为GMSK就是MSK的“限带版本”。MSK的基本思想很简单:载波相位在每个比特持续时间内线性增加或减少π/2,所以调制指数h=0.5,相位路径是一棵连续的分支树——每个比特都让相位沿顺时针或逆时针方向转折90度。这种相位连续特性使MSK的频谱旁瓣比BPSK低很多,但主瓣宽度仍然偏大,频谱效率不够理想。
GMSK在MSK的基础上增加了一个前置高斯低通滤波器,对输入的矩形脉冲先做平滑,再用平滑后的波形控制相位变化速率。这样相位路径不再是一条条直线段首尾相接,而是被修圆了,高频分量被明显抑制,带外辐射更小。通常用BT乘积描述这个高斯滤波器的带宽,BT=0.3是工程上最常见的取值,GSM系统就是用它。BT=∞时高斯滤波器退化为全通,GMSK直接变成MSK,所以MSK可以看作GMSK的一个特例。
Matlab里生成GMSK基带波形,核心就三步:
% 参数设置 h = 0.5; % 调制指数 BT = 0.3; % 高斯滤波器带宽-时间乘积 Nsamp = 8; % 每符号采样点数 Rb = 1; % 符号速率归一化 % 1. 信息比特映射为±1 a = 2 * bits - 1; % bits为0/1序列 % 2. 高斯脉冲成形 % 对矩形NRZ波形做高斯滤波,等效于把冲激响应用高斯脉冲近似 [phase_inc, q] = gmsk_phase_pulse(a, Nsamp, BT, h); % 3. 相位积分,得到复数基带信号 phi = cumsum(phase_inc) * pi * h; s = exp(1j * phi);这里的高斯脉冲q(t)可以查标准定义:它是高斯函数对时间的积分,决定了单个比特相位贡献的时域窗口。BT越小,q(t)拖得越长,理想情况下相位脉冲会跨越多个符号周期,这就是MSK/GMSK“带记忆”的来源。
从工程角度理解,GMSK的相位成形可以看成发射端对原始比特流做了一次非线性变换。比特不再是直接反映在幅度或相位跳变上,而是反映在跨符号的相位增量上。这个特点决定了接收端不能用BPSK那种逐符号匹配判别的思路,必须考虑相位积累过程。
频谱效率方面,BPSK理想频谱无限宽,实际通过升余弦滤波器限带;GMSK靠相位平滑本身就限带。实测中BT=0.3的GMSK在归一化频率1.5附近频谱衰减能达到-60dB以下,占用带宽比BPSK小一倍左右。这是GMSK在工程上最大的价值——在带宽受限信道里能塞进更多用户或更高数据率。
3. 二比特差分解调:不看绝对相位,只看相位增量
GMSK接收端的经典做法是最大似然序列估计,可以用维特比算法在相位状态格上做。但序列检测复杂度高,工程上更常见的简化方案是差分检测。一比特差分检测简单、复杂度低,但信噪比损失较大;二比特差分检测在复杂度和性能之间取了一个很好的平衡点,而且对载波初始相位不敏感,非常适合突发通信和简化接收机。
二比特差分解调的原理要从相位增量说起。以MSK为例,若信息比特a(k)∈{±1},则第k个符号的相位增量近似为a(k)·π/2,跨两个符号周期的累计相位差为[a(k-1)+a(k)]·π/2。当相邻比特相同时,这个相位差收敛到±π;相邻比特不同时,相位差趋近于0。也就是说,二比特差分检测真正检到的是相邻两个比特的乘积a(k-1)·a(k),而不是单个比特本身。如果发射端预先做了差分编码b(k)=a(k)·b(k-1),接收端就能从二比特差分结果中直接恢复b(k)对应的信息序列。
实际操作中,直接计算接收信号的延迟共轭乘积更加简单:
% rx为接收基带波形,Nsamp为每符号采样数 z = rx(2*Nsamp+1 : end) .* conj(rx(1 : end-2*Nsamp)); % 或者逐符号采样后计算 % 取z的虚部或实部作为判决量,具体取哪个取决于映射约定 soft = imag(z); % 或real(z),极性需与差分编码映射对应为什么不取一比特差分?因为GMSK的相位脉冲跨符号延伸,一比特差分区间内相位增量受相邻码间干扰影响很大,判决裕量不足;取两比特间隔后,发生在中间的那个比特的影响被对称抵消,判决统计量的稳定性明显改善。BT越小,这个优势越明显。当然,二比特差分也有代价:等效噪声功率翻倍,信噪比损失大约比一比特差分少一些,但相比理想相干检测通常有3dB左右的代价。
得到soft量之后不能直接硬判决,Turbo译码需要的是对数似然比LLR。工程上最简单的做法是直接按噪声方差归一化:
% 差分噪声方差近似为原信道噪声方差的两倍 sigma2_diff = 2 * sigma2_n; LLR = soft / sigma2_diff;这个近似虽然粗糙,但对Turbo迭代译码完全够用——log-MAP译码器对LLR的绝对尺度并不敏感,只要极性正确、相对幅度合理,迭代依然能收敛到接近理想的性能。如果你希望在实验室误差范围内精确一点,可以先把difference软量的经验方差统计出来,再按比例归一化。
4. Turbo码编译码实现:迭代译码里的外信息闭环
Turbo码本质上是两个递归系统卷积码RSC通过交织器并行级联,接收端用两个软输入软输出译码器迭代交换“外信息”,逼近最大似然译码性能。这里每个术语都有具体含义:
- RSC分量码:必须带反馈结构,只有递归结构才能在低信噪比下形成有效的“香农逼近”效果。我用的生成多项式是[7 5](八进制),对应反馈多项式101、前向多项式111。
- 交织器:把同一段信息比特打乱顺序后送给第二个编码器,让两个分量译码器看到的错误图案尽量不相关。交织深度直接影响迭代增益。
- 迭代译码:分量译码器1解出信息比特的软信息,减去它自己的先验输入和外加信道信息,得到“外信息”交给译码器2;译码器2同样计算外信息反馈给译码器1。如此反复,两个译码器互相纠偏,误码率逐步下降。
Max-Log-MAP是我在Matlab里最常用的译码算法。它的核心是各路度量比较,不是完整BCJR的对数折算。为了保持迭代中的数值稳定性,需要处理全部路径度量的归一化,防止溢出。
关键是外信息提取这一步。分量译码器输出的是后验LLR,外信息定义为:
L_ext = L_posterior - L_a - L_c;其中L_a是来自另一个译码器的先验信息,L_c是信道对系统比特提供的软信息。BPSK链路里L_c通常就是2y/σ²,GMSK差分链路里则取第3节算出的soft归一化量。每次迭代填充L_a后,译码器更新L_posterior,再剪出新的L_ext给另一半。
我第一次实现时栽在了一个问题上:增益收敛不了,误码率曲线平到像是没有编码。后来单独检查每个模块的软信息输出,发现分量译码器1和2之间外信息的符号约定不统一。L_a加错了符号,两个译码器实际上在“反着推”,迭代当然越推越差。所以在调试阶段建议做一个无信道噪声的“完美接收”验证:把解调软信息直接替成理想映射值,如果Turbo译码器不能收敛到零误码,说明外信息符号或交织器索引有误。
迭代次数方面,实测Max-Log-MAP在4到6次迭代后性能曲线就基本重合,8次是性价比很高的选择。继续增加到十几轮,收益微乎其微,但运行时间线性上升,交织规模大时尤其明显。仿真里可以写个循环,绘制不同迭代次数下的BER曲线,直观展示迭代收敛过程。
5. 仿真链路搭建与关键结果:误码性能究竟差在哪
现在把各模块串起来,给出完整的仿真参数。我用的配置如下:
| 参数 | 取值 |
|---|---|
| 信息比特长度 | 1024 |
| Turbo码率 | 1/3 |
| 交织器 | 随机交织,固定随机种子 |
| 分量编码器多项式 | [7 5](八进制RSC) |
| 译码算法 | Max-Log-MAP,迭代8次 |
| 调制方式 | BPSK / GMSK(BT=0.3) / MSK |
| 差分检测 | 二比特差分(GMSK/MSK) |
| 过采样倍数 | 8符号/采样 |
| 信道 | AWGN |
| Eb/N0范围 | -0.5 ~ 4 dB |
链路主循环流程如下:生成随机信息比特,送入Turbo编码器;编码输出按码率打孔后调制;叠加噪声;解调;LLR归一化后送入Turbo译码器;统计误码率。蒙特卡洛仿真中每个信噪比点至少要跑到出现50个以上错误比特,曲线才平滑,否则高信噪比区域波动很大,看不出趋势。
跑出来的典型结果趋势如下(AWGN信道,1024信息比特):
| 方案 | 达到BER=1e-3所需的Eb/N0 |
|---|---|
| 无编码GMSK+二比特差分 | 约10dB |
| Turbo+MSK(二比特差分) | 约6.5dB |
| Turbo+GMSK(二比特差分) | 约7dB |
| Turbo+BPSK(相干解调) | 约5.5dB |
这个表不是精确标定,不同交织器长度和迭代次数会有差别,但相对趋势是稳定的:Turbo码给差分检测链路带来了约3dB以上的编码增益,代价是要用迭代译码换;BPSK链路因为相干解调软信息质量好,增益最高;GMSK由于频谱效率优势和包络恒定特性,在带宽受限场景下更有吸引力。如果拿MSK和GMSK对比,MSK差分检测的软信息更干净,性能略好;GMSK带宽效率更优,因此按频谱效率归一化后,GMSK的净优势还是明显的。
仿真过程中最容易搞错的Eb/N0标定,我单独强调一下。GMSK是恒包络信号,功率归一化后每符号能量Es、每比特能量Eb和码率R的折算关系是Eb/N0 = Es/N0 - 10log10(R),同时要把差分检测带来的噪声放大也算进去。最稳妥的验证方法:在BPSK链路上做一次无编码误码率测试,确认仿真曲线与理论曲线重合,再用同样的噪声口径切换到GMSK链路上。如果BPSK链路标定都偏了,GMSK差分链路的绝对信噪比就完全不可信。
6. 实测踩坑记录:软信息极性、相位展开、信噪比标定
这一段是实际操作中真正容易卡住的地方,我把踩过的坑按优先级列出来。
**软信息极性。**这是最隐蔽也最致命的问题。差分解调输出的软量极性如果和Turbo译码器的信息比特约定相反,高信噪比下依然可能接近50%误码。排查手段很直接:先给发射端一个已知序列,手动过一遍差分解调,观察软量符号与比特映射是否一致。不要只在译码端找问题,问题往往出在调制端映射约定和解调端判决方向两边的符号配合上。
**相位展开跳变。**计算相位差之前,如果直接用angle()取瞬时相位,会在±π边界产生跳变,导致差分软量出现毛刺。正确做法是对瞬时相位序列先做unwrap处理,再逐点求差。示例代码:
phi = unwrap(angle(rx)); delta_phi = phi(2*taps+1 : end) - phi(1 : end-2*taps); soft = sin(delta_phi); % 或cos,按调制约定unwrap的引入可能会让初学的人一头雾水,但只要画一下相位曲线就会看到,未展开的相位在边界处会有2π的跳变,这个跳变经过差分运算后会直接变成一个虚假的强“旋转”,完全掩盖真实的相位增量。
**差分噪声方差。**用2倍原噪声方差做归一化是工程近似,但如果信噪比走高后BER曲线出现异常上翘,不要急着怀疑Turbo译码器,先用差分解调的原始BER测试确认差分链路本身正确。差分检测的噪声样本实际上不是严格白噪声,相邻时刻存在相关性,所以在精确仿真里可以统计软量方差后一次性归一。
**交替验证Turbo码本身。**GMSK链路跑不通时,回到BPSK链路用同一套Turbo编译码器测试,是最快的排错手段。反过来,BPSK链路能跑到接近理论极限,也说明你手上的Turbo译码器实现是过关的,后面GMSK链路的性能差异都归因于调制解调方式,而不是编码器本身。
**迭代收敛与误差平台。**Max-Log-MAP在低信噪比时迭代增益明显,但高信噪比下误码率曲线可能出现误差平台,这时候增加迭代次数没有帮助,问题更可能在交织器长度或分量码的选择。适当增大交织长度、或改用完整log-MAP,可以推低误差平台。
GMSK与Turbo码的组合,最终要比的不只是编码增益,而是“带宽效率×功率效率”的综合收益。BPSK+Turbo很容易拿到好看的误码率曲线,但频谱代价高;GMSK+Turbo让发射机可以用非线性功放、频谱占用更省,同时靠Turbo的迭代增益补偿差分检测的损失——这在工程上的价值比单纯追求曲线更低误码率更实在。如果你只是做课设验证,建议先跑通Turbo+BPSK,再用相同的译码器切换到GMSK差分链路;这种逐层替换的方式,能在最短时间内帮你理清调制、编码、解调三者各自的贡献,也最容易写出让人信服的实验报告。