循环冗余校验CRC

网上搜到的内容不全面,维基百科讲的比较好,原理很清楚传送门。其实对于程序员来讲,不用太在意它的数学原理,另外生成码的选择不是随意的,这可能影响到校验的性能。

注意其中的加法不进位,减法不借位,类似是异或逻辑。

关于怎样产生CRC,有这样一个算法:

下面为CRC的计算过程: 
    1.设置CRC寄存器,并给其赋值FFFF(hex)。 
    2.将数据的第一个8-bit字符与16位CRC寄存器的低8位进行异或,并把结果存入CRC寄存器。 
    3.CRC寄存器向右移一位,MSB补零,移出并检查LSB。 
    4.如果LSB为0,重复第三步;若LSB为1,CRC寄存器与多项式码相异或。 
    5.重复第3与第4步直到8次移位全部完成。此时一个8-bit数据处理完毕。 
    6.重复第2至第5步直到所有数据全部处理完成。 
    7.最终CRC寄存器的内容即为CRC值。

modbus的手册上给出了权威的版本:

A procedure for generating a CRC is:
1. Load a 16–bit register with FFFF hex (all 1’s). Call this the CRC register.
2. Exclusive OR the first 8–bit byte of the message with the low–order byte of the 16–bit CRC register, putting the result in the
CRC register.
3. Shift the CRC register one bit to the right (toward the LSB), zero–filling the MSB. Extract and examine the LSB.
4. (If the LSB was 0): Repeat Step 3 (another shift).
(If the LSB was 1): Exclusive OR the CRC register with the polynomial value 0xA001 (1010 0000 0000 0001).
5. Repeat Steps 3 and 4 until 8 shifts have been performed. When this is done, a complete 8–bit byte will have been
processed.
6. Repeat Steps 2 through 5 for the next 8–bit byte of the message. Continue doing this until all bytes have been processed.
7. The final content of the CRC register is the CRC value.
8. When the CRC is placed into the message, its upper and lower bytes must be swapped as described below.

 

附上一段代码示例

u16 getCRCCode(u8* buf, int len)	//生成从buf开始的len个字节的CRC16码
{
	int i, j;
	u16 crc = (u16)0xffff;
	for (i = 0; i < len; i++)
	{
		crc ^= (u16)buf[i];
		for (j = 0; j < 8; j++)
		{
			if ((crc & 1) != 0)
			{
				crc >>= 1;
				crc ^= 0xA001;
			}
			else
				crc >>= 1;
		}
	}
    return crc;
}


 

posted on 2012-09-05 21:23  lxjsailor  阅读(288)  评论(0编辑  收藏  举报

导航