1 CRC数学原理:多项式表示、模2除法、余数计算、初值与异或值的作用
1.1 多项式表示与GF(2)算术
CRC校验的核心是将二进制数据视为系数仅为0或1的多项式,在GF(2)有限域中运算。一个n位二进制数的多项式表示如下:
| 二进制 | 多项式(最高幂次) | 说明 |
|---|---|---|
| 1011 | x³ + x¹ + x⁰ | 系数从高位到低位对应幂次n-1 → 0 |
| 110101 | x⁵ + x⁴ + x² + x⁰ | 缺位系数为0,不写项 |
GF(2)加法等效于异或,无进位无借位,减法与加法相同。例如:
多项式加法:x³ + x¹ + x⁰
+ x³ + x²
= x² + x¹ + x⁰ (x³抵消)
二进制位运算:1011 ⊕ 1100 = 0111
关键概念:CRC使用的生成多项式(Generator Polynomial)是双方约定的除数,通常用十六进制简写。例如CRC-16-CCITT:x¹⁶ + x¹² + x⁵ + x⁰ → 0x1021。
1.2 模2除法与余数计算
CRC计算核心是模2除法(无借位除法)。步骤:
- 将待保护数据左移r位(r = 生成多项式最高幂次),附加r个0作为被除数。
- 用生成多项式(除数)按位异或(模2减)被除数高位,每次对齐多项式最高位。
- 重复直到处理完所有位,最后的余数(位数 < r)即为CRC校验值。
以下示例展示数据 1011 (x³+x+1) 使用生成多项式 1101 (x³+x²+1) 计算4位CRC的模2除法过程:
被除数:1011 000 (左移3位)
除数 :1101
运算:(对齐最高位)
1011 000
⊕ 1101
-----
0110 000 (商的第一位1,余数移位)
110 000 (对齐)
⊕ 1101
-----
001 000 (第二位商0,下移一位)
01 000 (对齐)
⊕ 1101
-----
00 100 (第三位商0,下移一位)
0 100 (对齐)
⊕ 1101
-----
0 001 (第四位商1,最后余数001)
最终余数:001 → CRC = 001
余数特征:余数位数严格少于生成多项式位数;若余数为0,表示数据无差错(暂不考虑初值影响)。
1.3 初值与异或值的作用
标准CRC算法引入初值(CRC寄存器初始值)和输出异或值,用于处理特定场景:
| 参数 | 作用 | 典型值(CRC-16-Modbus) |
|---|---|---|
| 初值(Init) | 在计算前将CRC寄存器设置为非零值,避免前置0被忽略;使全0数据产生非零CRC。 | 0xFFFF |
| 输出异或值(XorOut) | 计算完成后将完整CRC寄存器与固定值异或,调整校验值分布。 | 0x0000(不异或) |
初值改变了计算过程的初始状态,输出异或值在最后一步做“显式翻转”。两者都是协议约定的标准化参数,蓝牙协议栈中常见CRC-16/CRC-32使用特定初值与异或值组合。
以CRC-16-IBM (初值0x0000, 异或0x0000) 与 CRC-16-Modbus (初值0xFFFF, 异或0x0000) 为例,相同数据产生不同校验值。
1.4 内联SVG:CRC计算流程与参数作用
易混淆点:初值在计算开始前写入寄存器,不是与结果异或;输出异或则是计算完成后对完整寄存器进行。两者顺序不可颠倒。蓝牙协议栈中CRC初值通常为0xFFFFFFFF(CRC-32)或0xFFFF(CRC-16),需查阅具体规范。
1.5 常见标准参数速查
| 算法 | 生成多项式 | 初值 (Init) | 输出异或 (XorOut) | 蓝牙应用 |
|---|---|---|---|---|
| CRC-32 | 04C11DB7 (x³²+...) | 0xFFFFFFFF | 0xFFFFFFFF | 蓝牙L2CAP、HCI数据包 |
| CRC-16-CCITT | 0x1021 | 0x0000 | 0x0000 | 蓝牙HCI命令事件 |
| CRC-16-Modbus | 0x8005 | 0xFFFF | 0x0000 | 蓝牙LL控制PDU |
理解初值与异或值的物理意义:初值使得全0的数据产生非零CRC,避免遗漏前导0;输出异或用于调整CRC的统计分布,提高检错能力。在蓝牙基带中,这两项是强制的标准参数,不可随意修改。