第2章 CRC数学原理:多项式除法、模2运算

2.1 从一次调试经历说起

几年前我做一批QSPI Flash固件升级模块,通信偶尔丢包。加了CRC校验后丢包率降了不少,但有一个特定数据模式总报错。我排查了半天,最后发现是CRC的数学实现出了岔子——模2除法的余数没对齐,直接把错位的数据当成了有效帧。

那次之后我彻底想明白一件事:CRC的可靠性,根子在数学原理上。多项式除法和模2运算看着像纸上谈兵,但哪一步理解不到位,工程上就会踩坑。这章我们就把它彻底掰开揉碎。

2.2 模2运算:CRC的"加减乘除"

模2运算说白了就是不带进位/借位的二进制运算。你想想看,普通加法里1+1=2要进位,模2加法里1+1=0,不进位。它只在乎"异或"的结果。

运算类型规则与普通运算的区别
模2加法0+0=0, 0+1=1, 1+0=1, 1+1=0无进位,等价于 XOR
模2减法0-0=0, 0-1=1, 1-0=1, 1-1=0无借位,与加法完全相同
模2乘法与普通二进制乘法步骤一致中间结果相加时使用模2加法
模2除法用XOR逐位相减,够除就上1,不够上0每一步都是异或,不比较大小

我个人习惯把模2运算记成"XOR全家桶"。加法是XOR,减法也是XOR,除法里的每一步还是XOR。你只要记住这一个操作,整套运算就通了。

快速记忆: 模2加法和减法结果一样,都用 XOR 算。1⊕1=0,0⊕1=1,仅此而已。

2.3 多项式表示:二进制与代数的桥梁

为什么CRC要把二进制数写成多项式?因为多项式的"次数"天然对应了数据的位权,而多项式除法恰好能生成一个紧凑的校验余数。

映射规则极简单:二进制数的每一位,就是多项式对应次数的系数。系数只能是0或1。

二进制多项式表示说明
1011x³ + x + 1最高位x³,最低位x⁰=1
1101x³ + x² + 1x¹项系数为0,省略
10011x⁴ + x + 1常用的CRC-4生成多项式
1 0000 0111x⁸ + x² + x + 1CRC-8 常见多项式之一

我在项目中见过有人直接把多项式当整数做除法,结果余数全错。记住:多项式除法的"次数比较"代替了整数除法的"大小比较",这是关键区别。

2.4 多项式除法:CRC计算的核心

算CRC的过程,本质上就是一次多项式除法。我们拿一个具体例子走一遍。

已知:

  • 原始数据:1101(多项式:x³ + x² + 1)
  • 生成多项式:1011(x³ + x + 1),记为G(x),次数n=3

计算CRC的步骤:

  1. 原始数据左移n位(补n个0):1101 000
  2. 用生成多项式1011,对1101000做模2除法
  3. 余数就是CRC值(取n位)

除法过程如下(每一步都是XOR):

         1011
      ________
1011 | 1101000
       1011
       ----
        1100  ← 第1次XOR结果
        1011
        ----
         1110  ← 第2次XOR结果
         1011
         ----
          101  ← 余数(3位)

余数是 101,这就是CRC-3校验值。把它附加到原始数据后面,得到编码结果:1101 101。

我曾经踩过的坑: 余数位数必须等于生成多项式的次数n。如果余数不足n位,高位补0。比如余数是01,要写成001。位数对不齐,接收端校验必失败。

2.5 CRC编码完整流程

上面这个例子,其实包含了CRC编码的全部数学环节。下面这张图把整个流程串起来,你一看就明白。

CRC编码数学原理流程 CRC编码数学原理流程 原始数据 D(x) (k bits) 数据左移n位 (补n个0) 生成多项式 G(x) (n+1 bits) 模2除法 (XOR) 逐位异或,不进位 CRC余数 R(x) (n bits) 编码结果 T(x) D(x) + R(x),k+n bits 左移 除数 被除数 余数 核心思想:用生成多项式对扩展数据进行模2除法,余数即为CRC校验值

流程很清晰:原始数据先左移,腾出n位空间放CRC;然后用生成多项式做模2除法,算出余数;最后把余数拼回去。接收方用同样的多项式再做一次除法,余数为0则数据无误。

2.6 工程避坑指南

数学原理搞懂了,但工程实现时还有几个细节容易翻车。我把自己踩过的坑列出来,你遇到时心里有数。

避坑一:多项式对齐

生成多项式最高位和最低位必须为1。最高位为1决定了余数的位数,最低位为1保证了能检测出奇数个错误。有些芯片手册给的多项式省略了最高位1,你补上才完整。

避坑二:初始值与结果异或

教科书上的CRC是"原始模2除法",但工程标准(如CRC-32)还加了初始值预设和结果异或。数学原理是基础,协议标准是变体,两者不矛盾。

避坑三:余数位数截断

前面说过,余数不足n位要补前导0。我在一个项目里忘记补0,CRC从8位变成了6位,两个错误码撞在了一起,排查了一整天才发现。

嗯,这章内容就到这。数学原理是CRC的根基,模2运算和多项式除法看似简单,但每一步都有细节。你拿纸笔手动算一次,比光看代码印象深得多。