多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

MATLAB实现(7,4)汉明码编译码仿真:生成矩阵、伴随式译码与误码率分析

MATLAB实现(7,4)汉明码编译码仿真:生成矩阵、伴随式译码与误码率分析 简介基于MATLAB的(7,4)汉明码编译码设计与仿真结果分析是一份完整的通信工程课程设计报告适合通信、电子信息类专业学生用于课程设计、毕业设计或自学纠错编码技术。资源围绕汉明码的核心知识点展开从线性分组码的H矩阵与G矩阵原理出发详细推导监督位关系式给出编码程序的设计步骤并通过加入噪声模拟信道干扰绘制信噪比与误比特数、误比特率曲线并对仿真结果进行分析。全文逻辑清晰包含大量公式推导和MATLAB实现思路报告排版规范公式清晰可直接参考报告结构、代码框架与结果分析方法。资源包仅含1个PDF文件大小659KB便于阅读和打印。已有235人学习下载适合正在学习数字通信、信道编码或需要完成类似MATLAB仿真设计的学生使用。 还在为上个月通信原理课程设计发愁的同学多半会在最后几天打开搜索引擎输入“MATLAB汉明码仿真”。这个项目看起来简单但真要把编码、译码、信道、误码率统计全部串起来还是有不少细节值得抠一抠的。这篇博文我用一个完整的(7,4)汉明码编译码设计与仿真作为主线把生成矩阵、校验矩阵、伴随式译码、BSC信道误码率分析这些环节全部过一遍代码和结果顺便聊聊我在跑这个仿真时踩过的坑。1. 为什么选(7,4)汉明码作为仿真切入点先聊点背景。(7,4)汉明码是线性分组码里最经典的例子之一信息位4位监督位3位码长7位最小码距3可以纠正单个随机错误。这个“能纠1位错”的能力让它成了通信原理课程里绕不开的教学范例。做MATLAB仿真选它有三个直接原因一是结构简单生成矩阵和校验矩阵都能用手算出来方便对照代码验证二是实现成本低不涉及复杂的译码迭代伴随式查表就能完成纠错三是它足够揭示纠错编码的核心逻辑——增加冗余、计算伴随式、定位错误、修正比特。这套流程学会了后面学BCH码、RS码、LDPC码思路是一致的。就我个人的经验来说(7,4)汉明码仿真还有一个容易被低估的价值它是测试“信道模型”和“误码率统计方法”的绝佳载体。因为码字短你可以把每个环节都打印出来观察从编码前的信息序列到加噪后的接收序列再到译码输出一步对应一步地检查这对理解整个通信系统非常有帮助。2. 编码器设计生成矩阵的构造与MATLAB实现2.1 生成矩阵背后的线性代数逻辑(7,4)汉明码的本质是把4位信息向量m通过生成矩阵G映射成一个7位码字c。这个映射是线性的用公式表示就是c m * G。注意这里的运算全部是二元域GF(2)上的模2运算。系统码形式的生成矩阵G由两部分拼接而成左边是4×4的单位矩阵I4右边是4×3的校验位生成矩阵P。这样一来编码输出的前4位就是原始信息位后3位是监督位。P矩阵的选取不是随意的它决定了码的纠错能力必须保证任意两列线性无关、任意三列可能线性相关但不能出现全零列。对于(7,4)汉明码一组常用的P矩阵是% 校验位生成矩阵 P (4行3列) P [1 1 0; 1 0 1; 1 1 1; 0 1 1];对应的生成矩阵G为[I4 P]。实际构造时可以直接用MATLAB的矩阵拼接功能建议使用逻辑数组而不是double数组这样后续模2运算直接用mod函数就能处理不用再转换数据类型。2.2 编码函数的完整代码编码的MATLAB实现可以分为两个层级。第一个层级是“单帧编码”适用于教学演示每输入一组4位信息输出一组7位码字function code hamming74_encode(msg) % msg: 1x4 的二进制信息位行向量 % code: 1x7 的 (7,4)汉明码码字 G [1 0 0 0 1 1 0; 0 1 0 0 1 0 1; 0 0 1 0 1 1 1; 0 0 0 1 0 1 1]; code mod(msg * G, 2); end第二个层级是“批量编码”用于仿真时对大量随机信息序列统一处理。这里的关键是用矩阵运算替代循环把N组信息排成一个N×4的矩阵一次性完成编码function codes hamming74_encode_batch(msg_batch) % msg_batch: N x 4 每行一组信息位 % codes: N x 7 每行一组编码输出 G [1 0 0 0 1 1 0; 0 1 0 0 1 0 1; 0 0 1 0 1 1 1; 0 0 0 1 0 1 1]; codes mod(msg_batch * G, 2); end批量处理时建议用稀疏矩阵或逻辑矩阵来节省内存当仿真数据量达到几十万帧时这个优化会明显缩短运行时间。我在最开始写仿真时没有注意这一点用double矩阵跑10万帧数据MATLAB直接卡了将近一分钟换成logical矩阵后瞬间完成。2.3 编码结果的验证方法编码器写完以后不要急着往下走先做一个小规模验证。用一组已知的信息序列检查输出是否与手动计算结果一致。比如输入[1 0 1 1]乘上G得到的结果应该是msg [1 0 1 1]; code hamming74_encode(msg); % 预期输出: 1 0 1 1 0 1 0从输出可以看到前4位就是原始信息位后3位监督位是通过P矩阵计算出来的。如果验证结果不对优先检查G矩阵是否构造正确尤其是行向量和列向量的对应关系以及mod运算是否遗漏。3. 译码器设计伴随式计算与错误图样的查表定位3.1 伴随式的物理意义译码是整个汉明码系统的灵魂。接收端拿到的是可能被噪声污染的7位序列r它等于原始码字c加上一个错误图样e同样在GF(2)上。我们现在面临的问题已知r如何判断哪一位出了错汉明码给出的答案是伴随式。定义校验矩阵H满足G * H 0。接收向量r乘以H的转置得到伴随式s r * H。如果s为全零向量说明r没有错误如果s非零s的取值恰好对应H矩阵中某一列的列号而该列的位置就是出错比特的位置。(7,4)汉明码的校验矩阵H一种常见形式是% 校验矩阵 H (3行7列) H [1 1 0 1 1 0 0; 1 0 1 1 0 1 0; 0 1 1 1 0 0 1];H矩阵的7列正好是1到7的二进制表示。这意味着只要算出3位伴随式s把它当成二进制数直接转换成十进制就能定位到具体错误位置。这种设计让汉明码的译码变得极其简单。3.2 单比特错误纠正的完整译码代码译码函数我采用了两步走的策略。第一步算伴随式第二步拿伴随式查表纠错。虽然这里用二进制转十进制的方法可以直接算出错误位置但为了代码可读性我习惯保留一张错误图样表方便初学者理解查表译码的思想function [dec_msg, corrected_code, error_pos] hamming74_decode(r) % r: 1x7 接收码字可能含1位错误 % dec_msg: 1x4 译码输出的信息位 % corrected_code: 1x7 纠错后的码字 % error_pos: 纠错位置0表示无错误 H [1 1 0 1 1 0 0; 1 0 1 1 0 1 0; 0 1 1 1 0 0 1]; s mod(r * H, 2); % 伴随式转十进制对应错误位置 error_pos s(1)*4 s(2)*2 s(3)*1; corrected_code r; if error_pos 0 corrected_code(error_pos) mod(corrected_code(error_pos) 1, 2); end % 取前4位作为信息位输出系统码结构 dec_msg corrected_code(1:4); end这里有一个细节值得注意H矩阵的列顺序决定了伴随式和错误位置的对应关系。如果你用MATLAB的通信工具箱里的hammgen函数来生成H矩阵列的排列顺序可能与上面手动构造的不同这会导致错误位置映射错误。解决方法是先从hammgen输出的H矩阵中提取列号映射表再做译码定位。3.3 批量译码与统计函数的实现做单个码字的译码验证之后就要考虑批量的仿真需求。批量译码的核心思路和一帧译码完全一样只不过要换成矩阵运算。假设接收矩阵R是N×7伴随式矩阵S计算如下function [dec_msgs, corrected_codes, error_nums] hamming74_decode_batch(R) H [1 1 0 1 1 0 0; 1 0 1 1 0 1 0; 0 1 1 1 0 0 1]; S mod(R * H, 2); error_pos_bin S * [4; 2; 1]; % N x 1 每行是错误位置 error_pos_bin error_pos_bin; N size(R, 1); corrected_codes R; for k 1:N pos error_pos_bin(k); if pos 0 corrected_codes(k, pos) mod(corrected_codes(k, pos) 1, 2); end end dec_msgs corrected_codes(:, 1:4); error_nums sum(error_pos_bin 0, 2); end这里用了循环来做逐行纠错虽然不优雅但胜在直观。如果要追求极致性能可以提前构建一个7×7的纠错掩码矩阵用索引直接批量翻转对应位置不过对于课程设计级别的仿真循环完全够用。4. 信道建模与完整系统仿真框架4.1 BSC信道的MATLAB建模汉明码最经典的信道模型是二进制对称信道BSC。它的逻辑很简单每个比特以概率p被翻转以概率1-p正确传输。MATLAB实现这段代码时有一个易错点随机数的生成要用rand与概率p比较而不是用randi。function received bsc_channel(codes, p) % codes: N x 7 发送码字矩阵 % p: 比特错误概率 % received: N x 7 经过BSC信道后的接收矩阵 noise rand(size(codes)) p; % 生成错误图样矩阵 received mod(codes noise, 2); end这行代码的效率相当高原因是MATLAB的rand矩阵生成和逻辑比较都是原生向量化操作。不需要循环遍历每个比特。值得注意的是这里的noise矩阵在每次调用信道的瞬间被生成如果想复现实验结果应该固定随机种子。4.2 完整仿真主程序的流程设计仿真的主流程按照“信息位生成→汉明编码→BSC信道传输→汉明译码→误码率统计”这条链路来搭建。我把误码率统计分成两个口径译码前误码率信道原始误码率和译码后误码率纠错后误码率对照这两个数字才能直观看出纠错编码带来的收益。clear; clc; rng(42); % 固定随机种子 total_bits 1e5; % 总信息位数 k 4; n 7; num_words floor(total_bits / k); % 生成随机信息位 msg_batch randi([0 1], num_words, k); % 编码 codes hamming74_encode_batch(msg_batch); % 遍历不同信道错误概率 p_values [0.001, 0.005, 0.01, 0.02, 0.05, 0.08, 0.1]; ber_before zeros(size(p_values)); ber_after zeros(size(p_values)); for idx 1:length(p_values) p p_values(idx); % 过信道 received bsc_channel(codes, p); % 译码 [dec_msgs, ~, ~] hamming74_decode_batch(received); % 统计误码率 ber_before(idx) p; errors_after sum(sum(dec_msgs ~ msg_batch, 2)); ber_after(idx) errors_after / (num_words * k); end % 输出表格 T table(p_values, ber_before, ber_after, VariableNames, ... {信道误码率p, 编码前误码率, 译码后误码率}); disp(T);4.3 对仿真数据量选择的思考很多人在写这个仿真时信息位数拍脑袋就定了导致误码率曲线毛刺严重。我建议至少取10万个信息比特即25000个(7,4)码字。为什么不选更少因为在p0.01时N个码字中发生错误码字的期望是N × (1-(1-p)^7)。以25000个码字算约有25000×0.0679≈1698个错误码字其中大部分是单比特错误少数是2比特错误。这个样本量足够让统计结果稳定下来。反过来说如果只跑1000个码字误码率曲线会跳得很厉害结论说服力大减。5. 仿真结果分析与误码率曲线的深入解读5.1 典型误码率结果表格解读某次仿真运行得到的结果如下数据仅供参考不同随机种子会有微小波动信道错误概率 p编码后无纠错时接收误码率译码后误码率平均每码字错误数0.0010.001约 0极少0.0050.005约 1.2×10⁻⁴0.00570.010.01约 6.8×10⁻⁴0.00340.020.02约 0.00360.01770.050.05约 0.02390.1180.10.1约 0.06570.328观察这个表格最明显的结论是在p0.001时译码后误码率几乎为0说明绝大多数错误码字都是单比特错误汉明码几乎全纠掉了。当p上升到0.05以上时译码后误码率逐渐接近甚至高于信道原始误码率的一半左右这是因为2比特错误大量出现而汉明码无法纠正2比特错误甚至可能出现“纠错反而纠错”的情况把原本正确的码字翻转成错误码字。5.2 误码率曲线的绘图与双对数坐标绘制误码率对比曲线时我通常会同时画出两条线一条是“无编码系统”的误码率曲线就是yx这条45度线另一条是“(7,4)汉明码编码系统”的译码后误码率曲线。使用双对数坐标后纠错编码带来的增益一目了然。figure; loglog(p_values, ber_before, k-o, LineWidth, 1.5, DisplayName, 无编码); hold on; loglog(p_values, ber_after, b-s, LineWidth, 1.5, DisplayName, (7,4)汉明码); xlabel(信道比特错误概率 p); ylabel(误码率 BER); legend(Location, northwest); grid on; title((7,4)汉明码在BSC信道下的纠错性能);一个值得在实验报告中讨论的点在低错误概率区汉明码的曲线下降得比无编码系统快得多这说明编码系统的误码率与p的幂次关系不同。理论上(7,4)汉明码的译码后误码率近似为二阶小量即当p很小时曲线斜率接近2而无编码系统曲线斜率是1。从双对数坐标图上看就是汉明码曲线更加陡峭。这个斜率差异本身就是纠错编码增益的直观体现。5.3 一个反直觉的发现高误码率下的纠错陷阱跑完高误码率仿真的人很容易察觉一个反直觉现象当p超过某个阈值对(7,4)汉明码大约是0.2左右后译码后的误码率反而可能高于不编码直接传输的误码率。原因在于汉明码按最小距离译码时遇到2比特以上错误会误判成另一个合法码字产生“错误传播”效应。这给我们两点启发一是纠错编码并不是万能的它对信道质量有一个最低要求二是仿真分析时不能只跑一个误码率点必须观察一整条性能曲线才能判断编码方案在什么范围内有效。6. 仿真中容易踩的坑和排查思路6.1 模2运算的类型陷阱最大概率翻车的地方是MATLAB的矩阵乘法没有天然的模2概念。直接使用msg * G得到的是十进制整数乘法结果必须套上mod(…, 2)才是GF(2)上的乘法。我第一次写编码函数时忘记了这一点导致输出码字里出现了2、3这样的数字后面的一切计算全乱套。排查方法很简单编码完打印几个码字出来检查合法码字必须全部是0或1。6.2 校验矩阵列顺序与错误定位的错位还有一次我在网上抄了一段hammgen(3)生成的H矩阵结果译码输出全是乱的。原因在于通信工具箱的hammgen生成的校验矩阵列顺序与我手动构造的不同导致伴随式到错误位置的映射关系错位。后来我在代码里加了这样一段自动映射% 自动生成错误位置映射表 error_map zeros(1, 7); for col 1:7 error_map(col) bi2de(H(:, col)); end用error_map去反查错误位置而不是直接把伴随式当成二进制数。这样无论H矩阵列顺序怎么变都能正确纠错。6.3 误码率统计口径不一致误码率统计还有一个容易被忽略的细节统计译码后误码率时应该以“信息位”为口径还是以“码字全部7位”为口径课程设计通常关心信息位误码率因为这才是端到端有效数据质量。我习惯统一用信息位统计即dec_msgs与msg_batch对比。如果拿7位码字来统计由于监督位本身也参与了纠错过程统计结果会与信息位误码率有细微差异分析时容易混淆。6.4 性能瓶颈在循环而不在信道如果仿真跑的比特数上了百万级性能瓶颈往往在批量译码函数里的逐行循环。一个实用的优化是预分配纠错掩码矩阵用单次矩阵运算替代循环。代码可以这样改% 预生成纠错掩码每行只在对应错误位置翻转 err_mask zeros(N, 7); linear_idx sub2ind([N, 7], (1:N), error_pos_bin); err_mask(linear_idx) 1; corrected_codes mod(R err_mask, 2);实测下来在25万帧数据规模下循环版本耗时约1.8秒向量化版本约0.2秒差距接近一个数量级。6.5 仿真结果与理论预期不一致时的排查顺序最后分享一个系统的排查方法。当误码率曲线明显偏离理论预期时按以下顺序检查先验证编码器——用已知输入对照手算结果再验证译码器——构造一个含已知单比特错误的码字看能否准确定位接着验证信道——将信道错误概率直接统计出来对比设定值最后检查统计口径——确保对比的比特位置一一对应。这套流程我每次写新的纠错码仿真都会执行一遍基本能在十分钟内定位问题所在。7. 从(7,4)汉明码往更深处延伸的方向(7,4)汉明码仿真做完以后如果想在这个方向上继续深入有三个不错的进阶方向。第一个是把信道从BSC换成AWGN信道配合BPSK调制把软判决译码做进去对比硬判决与软判决的性能差距。第二个是扩展到(15,11)汉明码比较码长对纠错性能和编码效率的影响。第三个方向更实用一些将(7,4)汉明码与交织器结合观察突发错误信道下的性能改善情况。就说扩展AWGN信道这一步MATLAB里只需把BSC信道替换成下面的流程码字先做BPSK映射0映射成11映射成-1叠加高斯噪声接收端做硬判决后再进入汉明译码。此时横轴从比特错误概率p换成信噪比Eb/N0绘制的误码率曲线会有更直观的“瀑布区”效果。有一点要提醒EB/N0计算时别忘了把编码冗余算进去码率R4/7会导致每个信息比特需要传输7/4个信道比特这意味着相比未编码系统要达到相同的信道比特信噪比需要更高的Eb/N0。在我个人的教学和带毕设经验里(7,4)汉明码仿真项目非常适合作为“第一个完整通信系统仿真”的练手项目。不要小看它简单从这套小项目里建立起的模块化仿真习惯、误码率统计思路、结果分析框架放到后面任意一个复杂的编码方案里都完全适用。希望这份拆解能让你少走一些弯路跑出干净的仿真曲线。本文还有配套的精品资源点击获取
返回列表