本篇介绍crc代码详解
crc是发送的数据为多项式取余,最后得到的余数,这个取余并不是真正的取余,而是模二取余,即异或 ^
以下列代码为例
#define CRC_POLYNOMIAL 0x131 // P(x) = x^8 + x^5 + x^4 + 1 = 100110001
unsigned char crc8_calc(unsigned char data[], unsigned int n) {
unsigned char crc = 0xFF; // calculated checksum
unsigned char bit; // bit mask
unsigned int i; // byte counter
for (i=0; i < n; i++) {
crc ^= (data[i]);
for (bit=8; bit > 0; --bit) {
if (crc & 0x80)
crc = (crc << 1) ^ CRC_POLYNOMIAL;
else
crc = (crc << 1);
}
}
return crc;
}
crc初始值可以为0,也可以为0xFF,当为0时,与数据本身异或得到数据本身,当为0xFF时,与数据异或得到数据取反,取0x0还是0xFF取决于 crc算法本身
多种crc算法的初始值不同,有固定规定,比如crc16_ccitt的crc初始值为0xFFFF, 而crc16_modem算法的crc初始值为0x0
当数据首位为0时,不需要计算,直接移动到下一位(和数据取余数相同,被除数为0的话不需要计算),当数据为1时,需要进行异或,为什么要(crc << 1)再异或crc多项式呢,因为crc多项式的最高位一定为1,1和1异或一定为0,所以可以省去这一步,直接计算下一位,所以所有的crc校验码都是最高位多一位,方便计算
crc多项式比对应位数多1位,如crc16的多项式,0x11021, 其实计算用的是0x1021
crc8的多项式,0x131,其实计算用的是0x31
CRC8:多项式是X8+X5+X4+1,对应的数字是0x131
CRC12:多项式是X12+X11+X3+X2+1,对应的数字是0x180D
CCITT CRC16:多项式是X16+X12+X5+1,对应的数字是0x11021
ANSI CRC16:多项式是X16+X15+X2+1,对应的数字是0x18005
参考如下文章,强烈推荐参考文章学习CRC校验法
https://blog.csdn.net/u013073067/article/details/86621770