CRC校验算法原理
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
CRC-12 CRC-16 CRC-16-CCITT CRC-32 CRC-32C
+ + + + +
+ + + + +
+ +1 +1
+1
0x80f 0x8005 0x1021 + + +1 +1 0x04 C1 1D B7 0x1E DC 6F 4本算法 以下均以 CRC-16-CCITT 为例进行说明,CRC 校验码为 16 位,生成多项式为 17 位。假如数据流为 4 字节:BYTE[3] BYTE[2] BYTE[1] BYTE[0],数据流左移 16 位,相当于扩大了 256×256 倍,再除以生成多项式 0x11021,做不借位的除法运算(相当于异或) ,所得的余数就是 CRC 校验码。发送数据时的数据流为:BYTE[3] BYTE[2] BYTE[1] BYTE[0] CRC[1] CRC[0]。 3 计算机比特算法 (1) 将扩大后的数据流(6 字节长度)高 16 位(BYTE[3] BYTE[2])放入一个长度为 16 位的 CRC 寄存器; (2) 如果 CRC 寄存器中的数据首位为 1,将寄存器左移 1 位(寄存器的最低位从下一个字节获得),再与生成多项式的简记式求异或,否则 仅将寄存器左移 1 位(CRC 寄存器的最低位从下一个字节获得); (3) 重复第(2)步,直到数据流全部移入 CRC 寄存器; (4) 最终 CRC 寄存器中的值则为 CRC 校验码即为:CRC[1] CRC[0]。
式中,Y[n] — 为 BYTE[n]字节的校验码,16bit 位宽。 由此可得,BYTE[n-1]字节的校验码为 BYTE[n]字节的校验码的高 8 位与当前字节异或求校验码,其结果再与上一字节的低 8 位左移 8 位异或,最终求得结果结尾当前字节的校验码,程序代码见附录 2。 4.3 32 位字节型 CRC 校验 可以参照 4.2 推导类似的公式。
CRC8 = (BYTE[n] × 256 +BYTE[n − 1] × 256
+ … +BYTE[1] × 256 +BYTE[0] × 256 )× 256 / G17 × 256 +…+BYTE[1] × 256 × 256 +BYTE[0] × 256 × 256 ) / G17 × 256 /G17 +…+ BYTE[1] × 256 × 256 /G17 + BYTE[0] × 256 ×
CRC8 = (BYTE[n] × 256 × 256+BYTE[n − 1] × 256 CRC8 = [ ]× [ ]/ × )× /
+ BYTE[n − 1] × 256 + BYTE[n − 1] × 256 [ − ])/ ×
CRC8 = ( [ ] +
CRC8 = Z[n] × 256
+ {( [ ] +
2 CRC-16 字节型校验算法 2.1 代码 2.1 计算当前字节 CRC-16 校验码(大端格式) u16 crc16_byte(u16 crc, const u8 data) { return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff]; } 2.2 代码 2.2 计算当前字节 CRC-16 校验码(小端格式) u16 crc16_byte(u16 crc, const u8 data) { return (crc << 8) ^ crc16_table[((crc >> 8) ^ data) & 0xff]; } 2.3 代码 2.3 计算数据流 CRC-16 校验码 /** * crc16 - compute the CRC-16 for the data buffer * @crc: previous CRC value * @buffer: data pointer * @len: number of bytes in the buffer * * Returns the updated CRC value. */ u16 crc16(u16 crc, u8 const *buffer, size_t len) { while (len--)
1.3 代码 1.3 计算数据流 CRC-8 校验码 /* * crc8 - calculate a crc8 over the given input data. * * table: crc table used for calculation. * pdata: pointer to data buffer. * nbytes: number of bytes in data buffer. * crc: previous returned crc8 value. */ u8 crc8(const u8 table[CRC8_TABLE_SIZE], u8 *pdata, size_t nbytes, u8 crc) { /* loop over the buffer data */ while (nbytes-- > 0) crc = table[(crc ^ *pdata++) & 0xff]; return crc; }
/
+
[ − ]×
/
}×
+…+
BYTE[1] × 256 ×
256 /G17 + BYTE[0] × 256 × 256 /G17 CRC8 = Z[n] × 256 + {( BYTE[0] × 256 × 256 /G17 在上述推导过程中,可以看出 BYTE[n-1]字节的校验码为, [ − ]=( [ ]/ × +( [ ]+ [ − ]) × / [ ]/ × +( [ ]+ [ − ]) × / }× +…+ BYTE[1] × 256 × 256 /G17 +
+ BYTE[n − 1] × 256
+ BYTE[n − 1] × 256
× 256 /G17 +…+ BYTE[1] × 256 × 256 /G17 + BYTE[0] × 256 ×
[ − ]) ×
/
}×
+…+ BYTE[1] × 256 × 256 /G17 + BYTE[0] ×
[ ]) ×
CRC 校验算法原理
── L.K. 2015-08-30 0 引言 CRC 算法已经有比较经典的现成代码可供我们使用,CRC 计算可以靠专用的硬件来实现,但是对于低成本的微控制器系统在没有硬件的 支持下实现 CRC 校验, 关键问题就是如何通过软件来完成 CRC 计算, 也就是 CRC 算法的问题。CRC 校验的基本思想是利用线性编码理论, 在发送端根据要传送的 k 位二进制码序列,以一定的规则产生一个校验用的 r 位监督码(即 CRC 码) ,并附在信息后面,构成一个新的二进 制序列数共(k + r)位,最后发送出去。在接收端,则根据信息码之间所遵循的规则进行检验,以确定传送中数据是否出错。 1 生成多项式 任意一个由二进制位串组成的代码都可以和一个系数为 0 或 1 取值的多项式一一对应。 例如: 代码 1010111 对应的多项式为 + 1,而多项式 + + + + + +
在上述推导过程中,可以看出 BYTE[n-1]字节的校验码为, [ − ] = ( [ ]+ [ − ] )/
式中,Y[n] — 为 BYTE[n]字节的校验码。 由此可得,BYTE[n-1]字节的校验码为 BYTE[n]字节的校验码与当前字节异或,异或结果再计算校验码。综合以上分析,通常可以计算出 从 0 至 255 的 8 位数据的校验码,在字节校验码算法中查表实现,程序代码见附录 1。 4.2 16 位字节型 CRC 校验 若设数据流为 BYTE[n] BYTE[n-1] BYTE[n-2] …BYTE[2] BYTE[1] BYTE[0],校验码的生成多项式为 G9。若计算 8 位 CRC 校验码,则 将数据流左移 8 位,再除以生成多项式 G9 便可得到 8 位 CRC 校验码。 具体推导过程如下所示,
5 总结 综合以上分析,可以看出 CRC 校验,采用查表法计算量较小,程序执行效率也较高,这也是实际情况中我们常采用的方案。同时对于硬 件 CRC 也可以看出有较大的优势,由于数据通常在传送线中也位串的方式发送的,在发送数据的同时采用硬件 CRC 可以较小的占用软件资 源。
附录
1 CRC-8 字节型校验算法 1.1 代码 1.1 CRC-8 校验码表格生成(高位先发) /* * crc8_populate_msb - fill crc table for given polynomial in reverse bit order. * * table: table to be filled. * polynomial: polynomial for which table is to be filled. */ void crc8_populate_msb(u8 table[CRC8_TABLE_SIZE], u8 polynomial) { int i, j; const u8 msbit = 0x80; u8 t = msbit; table[0] = 0; for (i = 1; i < CRC8_TABLE_SIZE; i *= 2) { t = (t << 1) ^ (t & msbit ? polynomial : 0); for (j = 0; j < i; j++) table[i+j] = table[j] ^ t; } }
4 计算机字节算法 4.1 8 位字节型 CRC 校验 若设数据流为 BYTE[n] BYTE[n-1] BYTE[n-2] …BYTE[2] BYTE[1] BYTE[0],校验码的生成多项式为 G9。若计算 8 位 CRC 校验码,则 将数据流左移 8 位,再除以生成多项式 G9 便可得到 8 位 CRC 校验码。 具体推导过程如下所示, CRC8 = (BYTE[n] × 256 +BYTE[n − 1] × 256 + … +BYTE[1] × 256 +BYTE[0] × 256 )× 256 / G9 × 256+…+BYTE[1] × 256 × 256+BYTE[0] × 256 × 256) / G9 × 256/G9 +…+ BYTE[1] × 256 × 256/G9 + BYTE[0] × 256 × 256/G9 × 256/G9 +…+ BYTE[1] × 256 × 256/G9 + BYTE[0] × 256 × 256/G9 }× +…+ BYTE[1] × 256 × 256/G9 + BYTE[0] × 256 × 256/G9
1.2 代码 1.2 CRC-8 校验码表格生成(低位先发) /* * crc8_populate_lsb - fill crc table for given polynomial in regular bit order. * * table: table to be filled. * polynomial: polynomial for which table is to be filled. */ void crc8_populate_lsb(u8 table[CRC8_TABLE_SIZE], u8 polynomial) { int i, j; u8 t = 1; table[0] = 0; for (i = (CRC8_TABLE_SIZE >> 1); i; i >>= 1) { t = (t >> 1) ^ (t & 1 ? polynomial : 0); for (j = 0; j < CRC8_TABLE_SIZE; j += 2*i) table[i+j] = table[j] ^ t; } }
+ 1对应的代码为 101111。在生成多项式中,通常最高位固定为 1,故在简记式中常忽略最高位,例如:
0x1021 实际是 0x11021。常用的标准生成多项式如表 1.1 所示。 表 1.1 常用标准的生成多项式 名 称 CRC-4 CRC-8 CRC-8 CRC-8 + + + + +1 + + + +1 +1 + + + 生成多项式 0x3 0x31 0x07 0x5e 简 记
CRC8 = (BYTE[n] × 256 × 256 +BYTE[n − 1] × 256 CRC8 = 256 /G17 CRC8 = ( [ ] + 256 /G17 CRC8 = Z[n] × 256 256 × 256 /G17 CRC8 = Z[n] × 256 + {( [ ]× + + {( [ ] × / + [ ]/ )× [ ]× × /