CRC介绍
在计算机通信过程中,由于存在外界信息干扰所以发送的数据存在错误的情况。为了保障通信的可靠性就需要对数据进行校验,通常有检错和纠错两种方式,纠错通过多个冗余位对数据位的交叉检测来实现,比较常见的是海明码;而检错只需要确认数据是否发生错误无需对错误位纠正,相对添加的冗余位就会少一些,常见的就是CRC校验算法。
- 模2除法
首先介绍一下模2除法。类似与数学中的竖式除法,但会进行异或运算。比如
1011001011前4位与1011进行的异或运算,其他过程与竖式除法相同。 - CRC原理
在发送节点发出的比特流是需要校验的数据,假设有m位,在模2除法中做被除数。除数是约定好的一个“生成多项式”。比如生成多项式为g(x)=x8 +x5 + x4 + 1,对应的二进制数为每项的系数,为1 0011 0001。生成多项式对发送方和接受方都是约定好的,发送方将计算的CRC校验位加到数据流末尾,接收方对收到的数据流同样做模2除法,如果能整除就说明数据无误。
CRC计算
下面介绍CRC计算过程,这里约定生成多项式为g(x)=x8 +x2 + x1 + 1,即1 0000 0111。由于CRC8 多项式的最高为都为1,并且在代码的crc8计算中,最高位也是不使用的, 所以在多项式记录时都去掉了最高位,即0000 0111。假设传送的比特流为1100 1010.
CRC8标准生成多项式
CRC-8 x8+x5+x4+1 0x31(0x131)
CRC-8 x8+x2+x1+1 0x07(0x107)
CRC-8 x8+x6+x4+x3+x2+x1 0x5E(0x15E)
计算过程:
- 数据左移8位(8位的0用于存储计算之后生成的校验码)
1100 1010 0000 0000 - 就行模2除法运算
生成的校验码为0x78。
然后将生成的校验码与传输的数据相或|
1100 1010 0000 0000 | 0111 1000 = 1100 1010 0111 1000(CA 78)
生成的CA 78用于传输,当接收方收到CA 78之后再根据约定的生成多项式计算余数,如果余数为0说明数据无误。
3. C语言实现
int main()
{
unsigned char data[8] ={ 0xCA, 0x20, 0x30, 0x40, 0x50, 0x60, 0xCA, 0xCA};
unsigned char CRC8 = 0;
CRC8 = CRC(data);
printf("%x", CRC8);
return 0;
}
unsigned char CRC(unsigned char *data)
{
unsigned char crc = 0x00;
unsigned char poly = 0x07;
for (int i = 0; i < 1; i++)
{
crc = crc ^ data[i];
for (int j = 0; j < 8; j++)
{
if (crc & 0x80)
{
crc = (crc << 1) ^ poly;
}
else
crc <<= 1;
}
}
return crc;
}
对于多个字节计算CRC,在每计算完一个字节之后,将得到的CRC与后续字节相异或,再按照计算方式计算即可。