CRC是什么?
CRC校验计算速度快,检错能力强,一些芯片支持编码器等硬件电路实现。从检错的正确率与速度、成本等方面,都比奇偶校验等校验方式具有优势。因而,CRC 成为计算机信息通信领域最为普遍的校验方式。
完整的crc模型应该具有一下特征:
- 参数模型Name
- 生成的数据宽带,如CRC-8,生成的crc校验码为8位,CRC-32生成的校验码为32位
- 多项式,比如x8+x2+x+1,二进制为100000111, 转换为十六进制省略最高位为0x07
- 初始值INIT,与数据宽带一样
- 原始数据是否反转REFIN,为true或者false
- 输出的crc值是否反转,大小位交换,比如 1010翻转后为0101
- 计算结果与此参数进行异或运算XOROUT,结果与位宽一致
得出一个数的CRC校验码还是比较简单的:
- 选定一个CRC生成多项式G(x);
- 将发送数据左移K位,右侧补零(其中K为生成多项式最高次幂);
- 用移位补零后的数据对G(x)进行模2除法(其实就是异或运算);
- 用得到的余数即为该数据的CRC校验码;
CRC校验数据整计算
在嵌入式通讯中,比如ota,modlbus,uart,在数据包里都会包含校验值,通常数据包的格式如下:
typedef struct {
char type; //消息类型
int len; //数据长度
unsigned char* data; //数据
unsigned int check; //crc32校验值
}node_date_t;
如何对整个数据帧进行校验:
一个数据的校验结果要作为下一个数据校验过程中移位寄存器的初值,如此循环往复在数据帧的下一拍就能输出整个数据帧的校验值了
CRC32校验码生成
uint32_t CRC32(uint_8 *data, uint16_t len)
{
//多项式 x32+x26+x23+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
//最高位省略,即100 1100 0001 0001 1101 1011 0111
uint32_t poly = 0x4c11DB7 ;
uint32_t init_value = 0xffffffff;
uint_8 datai;
while(len--){
init_value ^= *data << 24 ; //左移24位与初值进行异或
//利用for循环,对每一位数据进行处理,如果是1,新值左移一位后与多项式进行异或,
//如果是0,仅左移
for(int i = 0; i < (sizeof(uint_8) * 8); i++){
if(init_value & 0x8000000)
init_value = (init_value << 1) ^ poly;
else
init_value <<= 1;
}
data++;
}
return init_value;
}