CRC(Cyclic Redundancy Check)校验应用较为广泛,以前为了处理简单,在程序中大多数采用
LRC(Longitudinal Redundancy Check)校验,LRC 校验很好理解,编程实现简单。用了一天时间
研究了 CRC 的 C 语言实现,理解和掌握了基本原理和 C 语言编程。结合自己的理解简单写
下来。
1、CRC 简介
CRC 检验的基本思想是利用线性编码理论,在发送端根据要传送的 k 位二进制码序列,以一
定的规则产生一个检验码 r 位(就是 CRC 码),附在信息后面,构成一个新的二进制码序列数
共(k+r)位,最后发送出去。接收端根据同样的规则校验,以确定传送中是否出错。接收端有
两种处理方式:
1、计算 k 位序列的 CRC 码,与接收到的 CRC 比较,一致则接收正确。
2、计算整个 k+r 位的 CRC 码,若为 0,则接收正确。
CRC 码有多种检验位数,8 位、16 位、32 位等,原理相同。16 位的 CRC 码产生的规则是先
将要发送的二进制序列数左移 16 位(即乘以 2 的 16 次方后),除以一个多项式,最后所得
到的余数就是 CRC 码。
求 CRC 码所采用的是模 2 运算法则,即多项式除法中采用不带借位的减法运算,运算等同
于异或运算。这一点要仔细理解,是编程的基础。
CRC-16: (美国二进制同步系统中采用) G(X) = X16 + X15 + X2 + 1
CRC-CCITT: (由欧洲 CCITT 推荐) G(X) = X16 + X12 + X5 + 1
CRC-32: G(X) = X32 + X26 + X23 + X22 + X16 +X12 + X11 + X10 + X8 + X7 + X5 + X4 + X2 + X1 + 1
2、按位计算 CRC
采用 CRC-CCITT 多项式,多项式为 0x11021,C 语言编程时,参与计算为 0x1021,这个地方
得深入思考才能体会其中的奥妙,分享一下我的思路:当按位计算 CRC 时,例如计算二进
制序列为 1001 1010 1010 1111 时,将二进制序列数左移 16 位,即为 1001 1010 1010 1111
(0000 0000 0000 0000),实际上该二进制序列可拆分为 1000 0000 0000 0000 (0000 0000 0000
0000) + 000 0000 0000 0000 (0000 0000 0000 0000) + 00 0000 0000 0000 (0000 0000 0000 0000)
+ 1 0000 0000 0000 (0000 0000 0000 0000) + ……
现在开始分析运算:
<1>对第一个二进制分序列求余数,竖式除法即为 0x10000 ^ 0x11021 运算,后面的 0 位保留;
<2>接着对第二个二进制分序列求余数,将第一步运算的余数*2 后再和第二个二进制分序列
一起对 0x11021 求余,这一步理解应该没什么问题。如果该分序列为 0,无需计算。
<3>对其余的二进制序列求余与上面两步相同。
<4>计算到最后一位时即为整个二进制序列的余数,即为 CRC 校验码。
该计算方法相当于对每一位计算,运算过程很容易理解,所占内存少,缺点是一位一位计算
比较耗时。 下面给出 C 语言实现方法:
unsigned char test[16] =
{0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff};
unsigned char len = 16;
void main( void )
{
unsigned long temp = 0;
unsigned int crc;
unsigned char i;
unsigned char *ptr = test;
while( len-- )