news 2026/9/12 3:49:57

从汉明码到LDPC:差错控制编码原理与工程实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从汉明码到LDPC:差错控制编码原理与工程实践

先问个问题:如果信道是理想的,我们还需要信道编码吗?答案是不需要——但现实世界从来没有理想信道。无线信号穿过空气会被衰减、反射、多径干扰,有线传输也躲不过热噪声和串扰。比特在信道上跑一圈,总会有那么几个被翻转、丢失或者错位。差错控制编码(也叫信道编码)就是干这个的:在发送端给信息比特有规律地加上冗余,让接收端不仅能发现错误,甚至能直接纠正错误。

这篇文章写的是我在学习和实践“差错控制编码(信道编码)”时沉淀下来的笔记,核心覆盖从最基础的奇偶校验、线性分组码、汉明码,到工程里最常见的循环码与CRC,再到卷积码、维特比译码、交织、级联码和现代Turbo/LDPC码的演进脉络。内容适合通信工程专业的学生、刚入行的基带算法工程师,以及做嵌入式通信协议开发的朋友参考。我会尽量把原理讲得接地气,同时把工程里真正会用到的参数、计算公式和踩过的坑一并写出来。

1. 为什么通信系统离不开差错控制编码

1.1 噪声与误码:现实信道没有理想通道

你可以在仿真里把信道设置为“无噪声”,但一旦设备搬进实验室、放到室外,事情立刻就变了。热噪声、冲击噪声、多径衰落、多普勒频移、邻频干扰……这些东西叠加在一起,会以随机或突发的方式破坏比特。以无线通信为例,一个符号经过调制后发射出去,信道的传递函数不可能完全平坦,接收端的信噪比(SNR)也不可能永远保持在理想值。当信噪比跌到某个门限以下,判决器就会开始犯错,误比特率(BER)直线上升。

这里有一个粗浅但重要的直觉:想要不增加发射功率、不改变调制阶数,只靠“重新发一遍”来对抗误码,在某些实时性要求高的业务里根本不可行。语音通话不能容忍你每错一帧就要求对方重说一遍;视频直播更是不能为了一个错误包就无限缓冲。所以,差错控制编码的思路是用“冗余换可靠性”——发送时故意多塞一些受控的校验信息,让接收端能够通过冗余来发现甚至纠正错误。

提示:误码率指标不能只看平均BER,很多工程场景真正关心的是“误帧率(FER)”或“误块率(BLER)”。信道编码方案的好坏,最终要看它对BLER这条曲线的改善程度。

1.2 差错控制编码在通信系统里的位置

如果把一个通信系统拆开,链路两端从信源到信宿一般会经过信源编码、加密、信道编码、调制、信道、解调、信道译码、解密、信源译码。信道编码紧挨着调制和解调,它处理的对象是已经变成0/1序列的二进制数据。信道编码的输入是信息比特,输出是经过规律性冗余扩展的编码比特;接收端拿到经过信道污染的解调软信息或硬判决结果,再做译码,还原出最可能的信息比特序列。

这里要引入一个概念叫“码率”(Code Rate),记作 R = k/n,表示每 n 个发送比特里有 k 个是真正有用的信息比特。R 越高,冗余越少,传输效率越高,但纠错能力通常越弱;R 越低,冗余越多,抗误码能力越强,但带宽利用率下降。后面讲到的所有编码方案,本质上都是在一个叫“香农限”的理论边界附近做权衡。

2. 差错控制的基本方式和系统框架

2.1 三种典型方式:ARQ、FEC、HEC

差错控制从系统层面看有三种实现方式,我在实际项目里都接触过,简单横向对比一下。

ARQ(自动重传请求):接收端检测到错误后,通过反馈信道请求发送端重传。这种方式实现简单,适合误码率不高、时延不敏感的场景。典型例子是TCP的分组重传。缺点很明显:反馈需要额外的信道资源,重传会带来不可控的时延,实时业务很难接受。另外在双向通信链路里,如果反向信道质量也很差,反馈本身也容易出错。

FEC(前向纠错):发送端直接发送足够多的冗余,接收端译码后自己纠错,不需要反馈信道。典型例子包括汉明码、RS码、卷积码、Turbo码、LDPC码。FEC的优点是时延固定、单向可用,非常适合广播、组播和实时流媒体。代价就是冗余占用带宽,而且在信道极差时,超过纠错能力的错误依然会漏过去。

HEC(混合纠错):把ARQ和FEC结合,常见做法是“轻量FEC + ARQ”。先靠FEC纠正大部分错误,剩下少部分无法纠正的再触发重传。这种方案在无线链路里很常见,比如许多无线通信系统里,物理层用FEC,MAC层或传输层再用ARQ兜底。工程上大家常说的“HARQ”(混合自动重传请求)就是HEC思想在标准里的落地形态,它把重传的旧数据与当前传输的数据做软合并,可以获得额外的分集增益。

2.2 如何衡量信道编码的代价与收益

衡量一种编码方案好不好,要看几个维度:

  • 编码增益(Coding Gain):在相同误码率条件下,使用信道编码后所需信噪比相对于未编码系统的降低量。比如在BER=10^-4时,某卷积码能带来4dB增益,意味着发射功率可以降低4dB,这对终端续航和基站覆盖都有直接价值。
  • 复杂度:译码算法的时间复杂度和空间复杂度。工程里经常遇到“理论增益1dB,但硬件资源翻倍”的尴尬选择。
  • 时延:编码块越大、交织越深,时延越大。语音等实时业务对时延极其敏感,不能为了增益无限增大编码块长度。
  • 误码平台(Error Floor):某些编码方案在高信噪比时,误码率曲线不再陡降,而是进入一个缓慢下降的平台区。这通常是由码字的最小距离分布太差或者译码器实现精度不够造成的。

3. 线性分组码:从奇偶校验到汉明码

3.1 线性分组码的结构

线性分组码是信道编码里最基础也最容易理解的一类码。所谓“分组”,是指每次取出 k 个信息比特,通过线性变换生成 n 个编码比特,记为 (n,k) 码。“线性”的意思是:任意两个合法码字相加,结果仍然是合法码字(模2加法)。

从数学上看,编码过程可以写为:

c = u × G

其中 u 是 1×k 的信息向量,G 是 k×n 的生成矩阵,c 是 1×n 的码字。这里的加法和乘法都是模2运算,也就是异或和与门逻辑。一个关键参数是最小汉明距离 d_min,它决定了纠错能力:

  • 可检测 e 个错误的条件:d_min ≥ e + 1
  • 可纠正 t 个错误的条件:d_min ≥ 2t + 1

这个关系是所有分组码设计的基石。d_min 越大,码的抗干扰能力越强,但通常伴随着更多冗余。

3.2 汉明码构造实例

汉明码是线性分组码里最经典的例子,最常见的 (7,4) 汉明码信息位 k=4,码长 n=7,最小距离 d_min=3,能够纠正任意1位错误,检测2位错误。

构造方式不复杂。设信息位为 u = [u1 u2 u3 u4],生成矩阵可以写成系统码形式:

G = [I4 | P]

这里 I4 是 4×4 单位矩阵,P 是 4×3 的校验位生成矩阵。编码后的码字前四位就是原始信息,后三位是校验位。比如取

P = [[1,1,0], [1,0,1], [0,1,1], [1,1,1]]

那么 c = u × G,得到的一个具体例子是:u = [1 0 1 1] 时,计算校验位得到 c = [1 0 1 1 | 0 0 1]。发送端就这样把7个比特送上信道。

接收端要纠错,需要用到校验矩阵 H。H 的构造满足 G × H^T = 0。对于上面的 G,(7,4)码的 H 通常是一个 3×7 矩阵。接收到 r 后,计算伴随式:

s = r × H^T

如果 s = 0,说明 r 是合法码字,大概率没错;如果 s 非零,根据 s 的值查表,就能知道是哪个比特错了,然后直接翻转纠正。这个“伴随式查表”的思路,在后面看CRC时还会再见,只是目标从纠错退回到了检错。

3.3 伴随式译码与查表纠错

伴随式译码的精髓是:把“找出错误位置”变成“查一次预计算好的表格”。还是拿 (7,4)汉明码举例,如果发送码字是 c,信道把第5个比特翻转,那么接收序列 r 与 c 只在第5位不同。此时 s = r × H^T = e × H^T,其中 e 是错误图样(只在第5位为1)。因为 H 的每一列都是不同的非零模式,所以 s 可以直接对应到具体的错误位置。

我在工程实践里发现,理解和手算一个(7,4)汉明码的完整过程,比单纯背公式管用得多。从手算中你能真正体会到:为什么 H 的列不能重复?如果两列一样,两种不同位置的错误就会对应同一个伴随式,译码器分不清,纠错就会出错。这个约束在所有线性分组码设计里都成立。

注意:汉明码虽然经典,但实际工程中很少用它作为唯一的FEC方案,因为它的码率不高(R=4/7≈0.57),纠错能力也只有1比特。它更适合作为教材案例和入门理解工具。真正工程里常用的是后面讲的CRC做检错、卷积码或LDPC做纠错,分工明确。

4. 循环码与CRC:工程中最常用的差错检测编码

4.1 循环码的代数基础

循环码是线性分组码的一个重要子类,特点是一个码字任意循环移位后仍是合法码字。这个性质可以用多项式来统一描述:把 n 位码字看成一个次数不超过 n-1 的二进制多项式,例如 1011001 对应多项式 x^6 + x^4 + x^3 + 1。循环码的生成完全由一个生成多项式 g(x) 决定,g(x) 是 x^n + 1 的因式,次数为 n-k。

编码过程在多项式视角下非常简洁:信息多项式 u(x) 乘以 x^(n-k),再用 g(x) 做模2多项式除法,余数就是校验位。接收端校验同理:把收到的多项式 r(x) 除以 g(x),如果余数为0,说明 r(x) 是合法码字,判定无误;余数非零,判定有错。

工程里大家最常接触的循环码就是CRC(循环冗余校验)。它不用于纠错,专门用于检错。因为它的检错能力非常强,而且硬件实现极其简单,所以在以太网、USB、Wi-Fi、存储系统里到处都是CRC的身影。

4.2 CRC计算的通俗解释与移位寄存器实现

CRC的计算表面上看是一堆多项式除法,实际上硬件实现就是一个带反馈的移位寄存器。常见的CRC标准有:

标准多项式应用场景
CRC-8x^8 + x^2 + x + 1传感器数据帧、简单通信协议
CRC-16-CCITTx^16 + x^12 + x^5 + 1Modbus、蓝牙、XMODEM
CRC-32x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1以太网、ZIP、GZIP、PNG

用多项式除法手算CRC的步骤可以这样记:先在数据比特后面补 n-k 个0,这个 n-k 等于生成多项式最高次数;然后用生成多项式对延长后的比特序列做模2除法,也就是异或运算,不借位不进位;最后得到的余数就是CRC校验值,替换掉之前补的0即可。

举个例子,数据比特为 1101,生成多项式为 1011(对应 x^3 + x + 1,最高次数3),所以在数据后补3个0,变成 1101000。用 1011 对 1101000 做模2除法,得到余数001。最终发送的码字就是 1101 001。

硬件实现时,n-k 位的移位寄存器与生成多项式的非零系数位置接异或门。数据逐位移入后,寄存器里留下的就是CRC值。这个过程没有除法器那种复杂的借位逻辑,几个触发器和异或门就能跑得飞快,这就是CRC能遍布各种高速接口的原因。

5. 卷积码与维特比译码

5.1 卷积码为什么适合连续比特流

分组码一次处理一个固定长度分组,信息比特之间没有跨越分组的记忆。卷积码不同,它有一个约束长度 K 的概念:当前输出不仅取决于当前输入比特,还取决于之前 K-1 个输入比特。也就是说,编码器是带状态(寄存器记忆)的有限状态机。

一个典型的 (n,k,K) 卷积码,k 表示每次输入比特数,n 表示每次输出比特数,码率 R = k/n。以工程里常见的 (2,1,7) 卷积码为例,码率1/2,约束长度7,编码器里有6级移位寄存器。每次输入1个比特,输出2个比特。这两个输出比特是当前输入和寄存器历史比特的模2线性组合。不同组合方式由生成多项式决定,比如最经典的133、171八进制生成多项式。

卷积码的好处是:它天然适合连续比特流的传输,不需要等到一个完整分组到齐才开始编码。这对语音、视频这种实时连续数据非常友好。而且它的纠错性能相当不错,配合维特比译码,在中等码率和中等约束长度下,能够提供接近最大似然译码的性能。

5.2 维特比算法的核心思想

维特比(Viterbi)算法是卷积码最常用的译码算法,它解决的问题是:给定一串接收序列,找出最可能的发送路径。

卷积码编码器从一个状态跳到另一个状态,整个编码过程可以画成一张网格图(Trellis)。对于 (2,1,K) 卷积码,状态数有 2^(K-1) 个,每个状态每个时刻有两条入边和两条出边。维特比算法不枚举所有可能的发送序列,而是在每个时刻对每个状态只保留一条“最可能到达该状态”的路径,称为幸存路径。这样做之所以不丢最优解,是因为网格图具有无记忆性质:从当前时刻到未来,路径的优劣只取决于当前状态,到达同一个状态的不同历史路径里,只有累计度量最小的那条值得保留。

实际工程中,维特比译码的度量常用汉明距离(硬判决)或欧氏距离(软判决)。软判决输入比硬判决通常能带来约2dB的增益,所以现在接收机里做卷积码译码时,几乎都会把解调器输出的软信息直接送给维特比译码器,而不是先硬判决成0/1再译码。

维特比算法还有一个工程细节叫“路径回溯深度”,一般取约束长度的5到10倍。如果回溯深度太小,路径还没收敛,译码性能会下降;太大则增加存储和时延。我在做FPGA实现时,一般取 (2,1,7) 卷积码的回溯深度为35到42之间,实测效果和理论性能已经很接近。

6. 交织、级联码与现代编码演进

6.1 交织:把突发错误打散成随机错误

信道产生的错误并不总是随机分布的。无线信道里的衰落、电力线信道里的脉冲干扰,会导致一连串比特连续出错。这种“突发错误”对许多纠错码来说非常致命,因为分组码和卷积码的纠错能力都是针对孤立错误设计的。

交织技术的思路很简单:发送前把编码后的比特顺序打乱,接收端再按相反顺序恢复。这样即使信道里发生了一段连续错误,经过解交织后,错误比特会被分散到不同的码字、不同的位置,变成“看起来像是随机错误”,纠错码就能正常工作了。

有两种常见交织方式:

  • 块交织:把编码比特按行写入一个矩阵,再按列读出。接收端按列写入、按行读出。若矩阵有 R 行 C 列,突发错误长度只要不超过 R,就能保证每行只分到1个错误。
  • 卷积交织:给每条支路增加不同的时延,实现连续比特流的交织。比块交织时延更低,适合实时业务。

设计交织深度时,需要同时考虑信道突发长度、纠错码纠错能力和业务时延预算。交织太浅起不到分散作用,太深会引入无法接受的时延。我在做突发干扰测试时,常常先用误码分布统计突发长度,再反推需要的最小交织深度,这样比拍脑袋定参数靠谱得多。

6.2 级联码与Turbo码、LDPC码的简要脉络

单个编码方案很难在所有维度同时做到最优,于是就有了级联码的概念:两个或多个编码器串起来用,内码负责纠正大部分错误,外码负责处理内码译码后残留的错误。最经典的级联结构是“外码RS + 内码卷积码”,曾经广泛用于深空通信和数字视频广播。RS码擅长纠正突发错误,卷积码擅长纠正随机错误,两者互补,效果相当好。

Turbo码的出现在1993年算是一次突破。它用两个卷积码编码器并行级联,中间通过交织器把两份校验信息分开,译码时两个译码器互相交换“外信息”,经过多次迭代逼近最大似然性能。Turbo码在接近香农限的地方表现优异,成为3G、4G移动通信里的主力编码方案。

LDPC码则是另一条路线,它的核心是一个“低密度”校验矩阵,即矩阵里1的个数非常少。LDPC用置信传播(Belief Propagation)算法迭代译码,在长码块、高码率场景下性能极好,而且并行度高、实现开销可控。5G NR的数据信道就把LDPC定为主力编码,控制信道仍然沿用Polar码。可以这么说:现代通信的系统设计中,“选哪种编码”已经变成“根据码长、码率、时延、吞吐和硬件复杂度寻找最佳折中”的问题。

7. 工程中的实践心得与常见误区

7.1 设计信道编码方案时最容易踩的坑

我在实际项目里见过不少因为对编码理解不深而反复返工的情况,整理几个典型:

第一,只考虑编码增益,不管时延和复杂度。有人在低时延业务里用了超长交织和超大LDPC码块,结果理论增益是好看,但端到端时延直接超标,最后只能推倒重来。正确的做法是先梳理业务的时延预算,再反推允许的最大编码块和交织深度。

第二,把CRC多项式选错。CRC虽然简单,但多项式选得不好,检错能力会明显下降。很多人直接网上抄一个多项式就用,没注意数据长度、LSB/MSB顺序和初值设置。不同标准对初值、输入反射、输出异或的处理都不同,代码里有一处不一致,算出的CRC就和协议对不上。

第三,硬判决代替软判决。对卷积码和Turbo/LDPC码来说,软判决信息能带来1.5到2.5dB的增益。有的项目为了简化设计直接用硬判决输入,结果白白丢了好几个dB的性能,后面为了提高覆盖又被迫增加发射功率,非常不划算。

第四,漏测突发干扰。很多测试环境只加白噪声,测出来的性能很好,一到现场遇到变频器、电机火花、开关电源等产生的脉冲干扰,错误就连串出现,纠错码当场失效。做信道编码验证时,一定要加入突发错误模型,并配合交织器一起测试。

7.2 常见问题速查表

我整理了一份实际调试中经常要查的问题对照表,遇到同类问题时可以直接按表排查。

问题现象可能原因排查与解决
译码后误码率不降反升发送端与接收端的生成多项式不一致核对编码器生成多项式、约束长度、码率是否完全一致
CRC校验一直失败字节序或初值设置不对检查LSB/MSB反射设置和CRC初值,用标准测试向量验证
卷积码性能比理论差很多使用硬判决而未用软信息将解调器的对数似然比(LLR)直接送入维特比译码器
突发干扰下性能崩溃没有加交织或交织深度不足根据实测突发长度增加交织深度,并加入交织器做整链路测试
LDPC译码在高信噪比出现平台迭代次数不足或量化精度不够增加最大迭代次数,检查输入软信息的定点化比特宽度
系统带宽利用率过低码率取得太低在满足BLER指标的前提下,逐步提高码率,用仿真找拐点

提示:信道编码是一项需要“整链路思维”的技术,任何一个环节不匹配,都会把编码增益吃掉大半。建议在项目早期就搭一套端到端的仿真环境,包含编码、调制、信道、解调、译码,所有参数可配置。这样调试一个参数的影响时,你能立刻看到全链路效果,而不是在孤立模块里反复猜测。

最后分享一点个人习惯

我做了这么多年通信底层,有一个习惯一直保留:拿到任何新的编码方案,先不用仿真工具,而是手工算一个最短码字的完整编码和译码过程。比如用笔算一个(7,4)汉明码,或者把一条卷积码的网格图画三五个时刻。这个过程看着慢,实际上能逼你把生成矩阵、校验矩阵、状态转移、伴随式这些概念全部过一遍,很多后面才暴露的bug,在手工计算阶段就能提前暴露。编码理论的公式并不难,难的是把“线性、冗余、状态、度量”这些概念真正串起来。等你亲手算通一次再去看FPGA代码或DSP代码,会明显感觉心里有底得多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 3:47:40

局部线性嵌入LLE:流形学习的原理、推导与NumPy实现

做流形学习的相关研究或课程作业时,局部线性嵌入(Locally Linear Embedding,LLE)这个名字总是绕不过去。它和 Isomap 一起被认为是流形学习领域的开山之作,2000 年发表在Science上时,给当时被 PCA 这类线性…

作者头像 李华
网站建设 2026/9/12 3:45:23

python的图论工业场景模拟第一百三十二篇:动态物料分配与通道失效韧性分析,任务:模拟通道随机失效,追踪最大流衰减输出韧性报告,图建模说明:动态有向图,删边与最大流迭代,核心点:动态失效韧性仿真。

⚠️ 前置说明:本篇是“网络流问题(第 7 章)”的韧性工程篇。核心目标是:在最大流算完之后,模拟传送带/管路/通信链路随机失效,观察最大流怎么掉、掉多少、掉在哪,输出一份“系统抗打击能力”报…

作者头像 李华
网站建设 2026/9/12 3:43:42

Smart Form跨系统传输与俄语多语言落地实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华