
在Simulink里搭通信模型这事儿做过的都懂——模块一拖线一连参数一设跑起来看误码率曲线。整个过程确实有点像拼乐高但拼完之后能不能动、跑出来对不对那又是另一回事了。今天咱们折腾的这个主题是给BPSK系统加上汉明码信道编码然后用误码率曲线说话看看那点冗余比特到底值不值。先说清楚这模型到底在干什么。整个系统就是一条典型的数字通信链路信源产生随机比特经过汉明码编码变成带冗余的码字再走BPSK调制映射到星座点上然后过AWGN信道加噪声接收端做BPSK解调、汉明码译码最后统计误码率。不加编码的BPSK做对照组加了汉明码的做实验组两边的误码率曲线拉出来对比。这个模型适合刚接触Simulink通信仿真、或者想搞明白信道编码到底带来多少增益的读者不管你是课程作业还是项目预研这套思路都能直接用。1. 项目玩法拆解汉明码BPSK到底在解决什么问题1.1 先把BPSK为什么值得用说透BPSKBinary Phase Shift Keying这名字听着唬人但说白了就是用两种相位去表示一个比特。举个例子0映射成11映射成-1然后在IQ平面上它就只有两个点——一个在实轴正方向一个在实轴负方向。这也是所有PSK里最简单的一种但它有它的底子两个星座点之间的欧氏距离是2在相同信噪比条件下BPSK的误码率是所有PSK里最低的那个。我经常和刚入门的人打比方BPSK就相当于在“开灯还是关灯”之间做判断而QPSK是“四个灯选一个”8PSK是“八个灯选一个”。灯越少判断越不容易错。BPSK把比特速率和符号速率做成1:1带宽效率不算高但它换来的是最容易实现的解调门限和最好的抗噪声底子。所以在做编码增益对比实验时用BPSK做基础调制是最不容易被其他因素干扰的。1.2 汉明码到底是什么给系统带来了什么汉明码是一种线性分组码最经典的(7,4)码每次拿4个信息比特生成3个校验比特凑成7个比特的码字发送。这3个校验比特不是随便加的它们分别对信息位做特定的异或运算使得接收端有办法判断“这7个比特里有没有哪一位出了问题”并且还能定位到具体是哪一位。换句话说(7,4)汉明码的最小汉明距离是3能纠正1比特错误或者检测2比特错误。汉明码的码率是4/7大约0.57意味着一半以上的信道资源用来传原始信息剩下将近一半是保护开销。那这开销买了一件事——在低信噪比区间把误码率往下压。后面仿真你会看到在同一个信噪比下加了汉明码的系统误码率能低一截正是因为有那么几个比特在帮整个码字扛伤害。1.3 编码增益这个东西用直觉怎么理解编码增益Coding Gain的定义并不复杂在同样误码率目标下编码系统需要的信噪比比未编码系统低多少。比如同样要到10^-3的误码率未编码的BPSK需要8.5 dB左右加了(7,4)汉明码的只要7.2 dB左右那编码增益就是1.3 dB。直觉上怎么理解你一个人穿越沙漠被晒晕的概率很高但如果派一个四人小队走每个人只要在自己负责的岗哨上盯着方向谁走偏了旁边人还能拉一把——这就是冗余的代价换来了容错能力。汉明码本质上就是用额外的校验比特构建这种“互相盯梢”的机制代价是发送同样多的原始信息你得花更多时间或者更多带宽收益是同样信道条件下错误率更低。2. 整体建模思路与关键参数设计2.1 模块级架构到底怎么排布Simulink建模这事最怕一上来就贪大求全。我的习惯是先画数据流的主干再回头补细节。这个模型的主干端到端就六段信源、编码器、调制器、信道、解调器、译码器最后加一个误码率统计模块收尾。旁路再接一路完全不经过编码的裸BPSK链路作为对照组也接到同一个误码率统计模块。很多人会问为什么不直接在同一个模型里做两个支路其实完全可以一条支路走编码一条支路不编码然后在误码率统计的时候分别拉数据就行。这样做的好处是信道噪声必须用同一个随机种子否则两个系统跑在不同的噪声样本上对比就不公平了。这是建模里最容易被忽略的细节后面我还要专门说。2.2 参数选型的核心依据下面这个表是我在这个项目里实际用到的一组参数你直接抄作业也行但最好还是理解每个参数为什么这么定。参数项取值选择理由汉明码类型(7,4) 汉明码最经典、最直观的纠错码适合做教学演示和原理验证信息比特数/帧4 kbit兼顾仿真速度和统计精度跑一次很快出结果调制方式BPSK星座点最少便于聚焦编码增益的对比信道模型AWGNEb/N0从0到10 dB覆盖从全乱到接近无误码的完整区间蒙特卡洛次数每种SNR跑10000帧以上保证误码率统计稳定特别是低误码率段关于信噪比的定义这里必须说清楚。我用的是每比特能量Eb/N0而不是符号信噪比Es/N0。两者的关系是Es/N0 Eb/N0 10*log10(k)其中k是每个符号携带的比特数。对于未编码BPSKk 1所以Es/N0 Eb/N0但对于(7,4)汉明码每个码字7个比特携带4个信息比特如果直接比较符号信噪比编码系统看起来反而更差因为它的符号能量分摊到了冗余比特上。所以一定要用Eb/N0来比较这样才能真正反映“每传一个信息比特”消耗的信噪比代价。2.3 为什么用AWGN信道而不是更复杂的信道很多新手喜欢一上来就上衰落信道或者多径信道我劝你打住。AWGN信道是通信系统仿真的“三好学生”——它有精确的理论误码率公式可以对照能让你快速确认仿真链路本身有没有bug。如果连AWGN信道下的误码率曲线都和理论对不上那后面加衰落信道更多是灾难。AWGN信道在Simulink里的实现也不复杂就是给调制后的复数信号加上高斯白噪声噪声功率由你设定的Eb/N0决定。关键是要把符号能量算对然后反推噪声方差后面我在第三部分会给出具体计算过程。2.4 设计里一个关键的取舍码率和频带利用率这里补充一点容易绕进去的地方。(7,4)码的码率是0.571所以如果你拿同样的符号速率去跑编码系统的信息速率会下降44%左右。这说明编码增益不是白拿的它是用频带利用率换来的。在实际系统里如果带宽很紧张你会考虑更高码率的码比如(15,11)汉明码码率0.733但纠错能力也相应下降。所以从项目层面来说选择(7,4)码就是为了把“编码能带来增益”这件事用最明显的方式展示出来。它纠错能力够强开销够直观数学也够简单——你在纸上都能手工算出一个错误码字的纠错过程。等你把这条链路跑通了再换其他码简直是一行参数的事。3. 核心模块搭建实操从空白模型到跑出第一张图3.1 环境准备和库选择Matlab版本建议R2020a以上不需要额外装别的工具箱Communications Toolbox就够用了。打开Simulink之后新建一个空白模型然后打开库浏览器Library Browser接下来的所有模块都从Communications Toolbox和Simulink自带库里拖。这个模型涉及的模块清单帮你列好照着找就行Bernoulli Binary Generator伯努利二进制信源Hamming Encoder汉明编码BPSK Modulator BasebandBPSK调制AWGN Channel加性高斯白噪声信道BPSK Demodulator BasebandBPSK解调Hamming Decoder汉明译码Error Rate Calculation误码率统计Display结果显示To Workspace数据导出用于画图Bit to Integer Converter和Integer to Bit Converter比特与整数转换汉明编解码用3.2 信源和编码器汉明码输入格式的坑第一个坑来自汉明编码器的输入格式。Hamming Encoder这个模块默认接收的是整数形式的消息——也就是说你给它一个0到15之间的整数它内部帮你转成4比特二进制然后输出7比特的码字。如果你直接用Bernoulli Binary Generator产生的0/1比特序列接进去它会报维度错误。解决办法有两个。第一个办法是在信源后面加一个Buffer把连续的比特流按4个一组缓冲然后用Bit to Integer Converter把4比特转成0~15的整数再喂给Hamming Encoder。第二个办法是直接把Random Integer Generator当成信源它天生就能产生0~15的均匀分布整数如果你不想在比特层面折腾这个更省事。我个人推荐第二个办法尤其是在做纯编码增益对比的时候。因为你关心的是编码前后误码率的变化不关心信源到底长什么样Random Integer Generator直接把信息符号喂给汉明编码器链路最短、坑最少。信源参数这样设Probability of a zero设为0.5Sample time设为1秒这里的“秒”是仿真时间不代表真实时间Samples per frame设为4000——这个数值决定了每帧携带4000个信息比特也就是1000个(7,4)码字。Initial seed设一个固定值比如37目的是确保每次仿真用同样的比特序列结果可复现。3.3 BPSK调制解调星座图和映射要搞清楚BPSK Modulator Baseband模块默认的星座映射是0映射到-1或者1不同版本可能不一样但从误码率统计角度只要调制和解调用同一个模块、同一种映射最终结果不受影响。你只需要在解调器里设置相同的Phase offset默认是0对应星座点在实轴上即可。调制器的Output type选Bit而不是Integer——因为这是BPSK一个符号就是一个比特选Bit最直观。星座点坐标在默认情况下是±1没有虚部。解调时如果你在后端只关心硬判决之后的比特就把Decision type设为Hard decision。如果后面接的是软译码器才需要Soft decision并设置软判决量化比特数。咱们这个项目用的是硬判决汉明译码所以选Hard decision就对了。3.4 AWGN信道信噪比参数必须按Eb/N0算AWGN Channel模块的参数设置是这个项目里最容易出错的地方。它的SNR参数既可以填Es/N0也可以填Eb/N0取决于你在“SNR”下拉框里选的是哪个。这里必须强调一定要选Eb/N0模式否则你后面比较编码和未编码系统的时候会得出完全错误的结论。为什么因为未编码BPSK一个符号就是一个比特Es和Eb相等数值上没区别。但编码之后一个码字包含7个比特其中只有4个是信息比特如果你还拿Es/N0来跑编码系统相当于“每接收6个冗余比特也在消耗你的等效信噪比预算”性能曲线会拉不开差距甚至看起来更差。AWGN Channel模块里还有一个容易忽视的参数——“Number of bits per symbol”。对于BPSK这个值就是1填好它之后模块才能在Eb/N0和Es/N0之间正确换算。如果你用的是(Q)PSK这里要填2用8PSK要填3千万别忘了。噪声种子Noise seed也建议设一个固定值比如67。这保证两轮仿真有编码和无编码用的是同一个噪声序列对比才有意义。3.5 误码率统计延迟对齐和输出格式误码率统计是整个链路里最需要耐心的地方。Error Rate Calculation模块比较发送端和接收端的比特序列但它要求两个序列在时间上对齐。由于汉明编码、译码以及调制解调都会引入延迟你必须在接收端序列上加一个Delay让两个信号在时间上对齐。灰色模块Receive delay设为0但发送端信号要先经过一个Delay模块延迟量设置为汉明编码器译码器的总延迟加调制解调延迟。实际操作中我一般这样处理先不接误码率统计模块用Scope同时观察发送端和接收端的信号数一下接收端信号比发送端晚了多少个仿真步长然后把这个值填进Delay模块。这个过程虽然土但绝对可靠。等调通之后再把Delay固定下来。Error Rate Calculation模块有三个输出误码率、错误比特数、总比特数。把它们分别接到三个Display上就能在仿真结束时直接看到数值。同时把这三个值用To Workspace导出方便后面在Matlab脚本里画误码率曲线。3.6 对照组链路的搭建对照组就是一模一样的链路唯一的区别是中间没有Hamming Encoder和Hamming Decoder信源直接进BPSK调制器解调后直接进误码率统计。这里注意由于没有编解码延迟对照组的Delay设置和实验组不同。你可以给两条链路各配一个独立的Delay模块也可以通过“仿真不同次数”来分别获取两组数据。我建议把两条链路放在同一个模型里用不同的变量名导出数据这样能确保共享同一个噪声模型。但也有人喜欢拆成两个模型分别跑各有各的好处——同一个模型便于对比两个模型便于调试。无论哪种方式核心原则是两组数据的信噪比范围设置完全一样。3.7 跑仿真脚本化循环别用鼠标一个个点仿真不是只跑一次而是要跑一组信噪比点。如果全靠鼠标在Simulink界面里改参数、点运行能把你点疯。我强烈建议把整个仿真循环写进一个Matlab脚本里用sim()函数控制Simulink模型运行每轮循环改一下AWGN信道的Eb/N0参数然后收集误码率。clear; clc; % 信噪比扫描范围单位dB EbN0_dB 0:1:10; ber_coded zeros(size(EbN0_dB)); ber_uncoded zeros(size(EbN0_dB)); for k 1:length(EbN0_dB) % 设置当前信噪比 set_param(hamming_bpsk/AWGN Channel, EbN0_dB, num2str(EbN0_dB(k))); % 跑仿真 simOut sim(hamming_bpsk, StopTime, 100); % 从仿真输出里取误码率 ber_coded(k) simOut.get(ber_coded); ber_uncoded(k) simOut.get(ber_uncoded); end % 画对比曲线 figure; semilogy(EbN0_dB, ber_uncoded, b-o, LineWidth, 1.5); hold on; semilogy(EbN0_dB, ber_coded, r-s, LineWidth, 1.5); grid on; xlabel(Eb/N0 (dB)); ylabel(误码率 (BER)); legend(未编码 BPSK, (7,4)汉明码 BPSK, Location, southwest); title(BPSK系统加入汉明码前后的误码率对比);这段脚本里用了set_param去改模块参数用sim去跑模型用simOut.get去取数据。前提是模型里已经用To Workspace把误码率存到了变量ber_coded和ber_uncoded里。这种脚本化方式还有一个好处——中途某轮出错了你能在命令行窗口看到是哪一组信噪比出了问题比在GUI里瞎猜高效得多。4. 仿真结果解读编码增益到底有多明显4.1 理论误码率公式先摆出来仿真结果要跟理论对得上才敢用。BPSK在AWGN信道下的理论误码率是[ P_b Q\left(\sqrt{\frac{2E_b}{N_0}}\right) ]其中Q函数是高斯Q函数在Matlab里可以用qfunc直接算。(7,4)汉明码加上硬判决BPSK解调理论上它的译码后误码率可以用码字错误率和信息位误码率的关系来推导公式稍微复杂一点但仿真是可以验证的。我在实操中会先把未编码BPSK的仿真曲线和这个理论公式画在一起。如果匹配得非常好说明链路基础是可靠的后续加编码才可信。4.2 仿真曲线怎么读从我实际跑出来的结果看曲线趋势大致是这样的在低信噪比区间0~3 dB两套系统的误码率都偏高但加了汉明码的下降速度更快因为纠错能力在噪声比较大的时候也能拉回一部分错误。在中等信噪比区间4~7 dB编码系统的优势最明显误码率可以比未编码系统低一个数量级以上。在高信噪比区间8 dB以上曲线越来越陡峭未编码系统也开始逼近无误码编码增益逐渐缩窄。如果硬要给个数字以误码率10^-3作为参考点未编码BPSK大约需要8.4 dB而(7,4)汉明码BPSK大约需要7.1 dB换算下来编码增益在1.3 dB上下。这个数字和许多通信原理教材里的结论是吻合的。4.3 为什么编码增益只有这么点值不值1.3 dB的增益看起来不多但别忘了这是码率高达0.57的简单纠错码能做到的。你不需要复杂的交织、不需要软判决、不需要迭代译码就靠3个奇偶校验比特就能把系统的等效灵敏度提高1.3 dB。在现实系统里1 dB的增益可能意味着发射功率可以降低约25%或者覆盖距离能提升12%左右这在工程上是实打实的收益。而且汉明码的译码延迟极低(7,4)码的译码只需要一个查表或者少量异或运算完全可以用在对实时性要求很高的控制链路上。相比之下LDPC或Turbo码的增益能有5~8 dB但代价是巨大的计算量和延迟。通信系统设计本质上就是在增益、复杂度、延迟、频带利用率之间找平衡汉明码处在平衡点的一个极端——简单、可靠、够用。5. 常见问题与排查技巧实录5.1 误码率统计出现“神秘延迟”怎么办症状是误码率占比高达0.5以上或者错误数一直在增加。这几乎可以断定是收发端没对齐。解决方法就是我前面说的把Delay模块的延迟量用Scope数出来。如果你的仿真步长是1秒一个码字是7个符号编码器加译码器通常会有几个符号的延迟数清楚之后填进去问题就消失了。5.2 汉明编码器报维度错误错误信息一般是“Dimension mismatch”之类。这就是因为你把比特流直接喂给了期望整数输入的Hamming Encoder。前面说过要么加BufferBit to Integer Converter要么干脆用Random Integer Generator当信源。我个人推荐后者因为对误码率研究的核心来说比特级信源反而引入不必要的转换步骤。5.3 AWGN信道的噪声种子要不要改不要改除非你刻意想验证多组噪声下的方差。做对比实验时固定种子就够了。如果既想固定又想在统计上更严谨你可以在每个信噪比点跑多次用不同的种子然后把误码率做平均。但我要提醒你——这个模型跑得很快真的需要统计平均的话跑100次也就几千秒的事对结果更可信。5.4 仿真结果和理论曲线偏离很大绝大多数情况下是信噪比模式选错了。如果你在AWGN模块里用了Es/N0而不是Eb/N0在编码系统上就会出现“伪增益”或者“伪损失”。还有一种可能是你忘了设置“Number of bits per symbol”导致模块内部换算错误。这两个坑检查完一般结果就对了。5.5 想扩展成软判决或更高阶调制怎么做软判决汉明译码在Simulink里实现相对复杂你得把BPSK解调器的输出设成Soft decision然后接一个支持软输入的自定义译码器。更高阶的调制比如QPSK、8PSK只需替换调制解调模块并把AWGN里的bits per symbol改成2或者3就行。汉明码部分不需要动因为编码是在比特层面做的。6. 这个项目还能怎么往下玩第一个方向是换码型。比如把(7,4)汉明码换成(15,11)汉明码你会看到码率提升了但纠错能力下降了。再把两者曲线放在一起对比可以直观理解“码率-冗余-增益”三者之间的关系。第二个方向是引入交织。现实信道里噪声突发可能会连续打掉好几个比特而汉明码只纠1个错误连续打掉多个就废了。在编码前加一个行列交织器把突发错误打散成随机错误汉明码就能重新发挥作用。这个改动在Simulink里就是加两个模块的事但背后的思想非常关键。第三个方向是软判决译码。如果不想局限于硬判决你可以把BPSK解调输出从0/1硬判决改成带置信度的软信息然后用汉明码的软判决译码比如基于最大似然的译码来提升增益。这条路会比硬判决多拿到约2 dB的额外增益。第四个方向是接入真实信道模型。Simulink自带的Multipath Rayleigh Fading Channel模块可以作为AWGN之后的一级看看多径对编码系统的影响。我个人建完这个模型之后最大的体会是通信系统仿真不是搭完模块就完事的真正花时间的永远是“让结果可信”这件事——延迟对齐、信噪比定义、随机种子控制、理论对照。这些细节没人提醒的话新手会踩得很痛。但一旦你把这些基本功练扎实了后面做任何通信链路仿真思路都会清晰很多。编码增益不是一个神秘的概念它就在你亲手跑出来的那条曲线上等着你把它解释清楚。