一. 什么是CRC
CRC是循环冗余校验,用于检测传输的数据的准确性。比如甲方给乙方发了一条消息,乙方收到消息之后,由CRC校验消息的准确性。
二. 原理
三. 使用HAL库函数HAL_CRC_Calculate直接计算
uint32_t Data_buffer[5] = {0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005};
uint32_t CRC_Value = 0;
uint8_t CRC_Result[4] = {0};//定义一个字符数组,用于存储最终CRC结果
CRC_Value = HAL_CRC_Calculate(&hcrc, Data_buffer, 5);
CRC_Result[3] = CRC_Value;
CRC_Result[2] = CRC_Value>>8;
CRC_Result[1] = CRC_Value>>16;
CRC_Result[0] = CRC_Value>>24;//读取CRC值到CRC_Result[4]数组中完毕。
HAL_UART_Transmit(&huart2, CRC_Result, 4, 500);//通过串口发送到PC端显示CRC值
四. 具体计算举例
现由服务端发送一条信息码10011001给客户端,信息码为原码,现在要加上CRC校验码,用于检测数据发送到目的地之后是否出错。那么CRC校验码如何计算呢?那就要用到“模二除法”。既然是除法,那就有被除数和除数,商,余数。但这里所说的被除数等和我们常用的算术除法不同
- 被除数:在信息码10011001的基础上,后面再加几个0(那么要加几个0呢?为什么要加0,我也不知道,算法的事情由数学家完成了,那么作为应用人员就学会如何使用吧!)
加多少个0 = 校验码位数 = 信息码位数-1 = 8 -1 = 7
所以加7个0; - 除数:这涉及到一个神奇的多项式:这个多项式是stm32内置CRC通用的多项式
X32 + X26 + X23 + X22 + X16 + X12 + X11 + X10 +X8 + X7 + X5 + X4 + X2+ X +1
X的0次幂累加到X的32次幂,次幂对应bit位
对应位 | 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 |
---|---|
各项系数 | 1 0 0 0 0 0 1 0 0 1 1 0 0 0 0 0 1 0 0 0 1 1 1 0 1 1 0 1 1 0 1 1 1 |
CRC每组32位,其中第33位应是符号位,可舍弃?请路过的大侠帮忙指证
(1)这个多项式的各项系数都是1,其他位的系数则是0,乘以0得0,所以省略了。
(2)多项式的次幂就是对应位0~32,它们的系数的组合就是需要的除数。
CRC每组32位,其中第33位是符号位,可舍弃
对应位 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
各项系数 1 0 0 0 0 0 1 0 0 1 1 0 0 0 0 0 1 0 0 0 1 1 1 0 1 1 0 1 1 0 1 1 1
写成16进制就是:0x04C11DB,该各项系数的组合数就是需要的除数。
3. CRC计算:被除数/除数,采用异或得到每一次的余数,最后的余数就是校验码。
由于stm32内置CRC计算有点长,就举一个下面短一点的计算例子:
计算说明:
(1) 商:只能是1和0的组合,余数满了除数的位数才商1,否则商0
(2)余数:每一次得到新的余数之后,如果少于除数的位数,就在余数后面补相邻的剩余位,直到被除数的剩余位为空,所得余数就是最后的校验码,这里要注意的是
校验码位数 = 信息码位数 - 1
所以如果余数的位数不够校验码位数,则在前面补0凑齐位数。