前言
CRC计算一般用于通信中,用来保证一组数据的完整性。 发送方发送一组数据dataA+CRC检验码CRCa(CRC校验码由数据算出); 接收方接收到数据dataA+CRC校验码CRCa,接收方通过与发送方约定好的计算公式,计算出一个CRC校验码CRCb, 如果CRCa = CRCb,则表示这一帧数据没有被篡改。有时候为了保证数据的连续性,也会加上一个rolling count。
一、原理
CRC原理可以参考文章: CRC8算法的解读,以及在E2E通信保护的应用_crc8查表法-CSDN博客
二、Autosar 规范
下面的这些参数非常重要,完全决定了你的CRC值对不对。
A: CRC result width: 8bit
B: Polynomial : 0x1D
C: Initial value : 0xFF
D: Input data reflected : NO
E: Result data reflected : NO
F: XOR value : 0xFF
三、Autosar示例验证
Autosar规范中给了一些例子,我将它分为7组
接下来我们打开下面的网页,针对上面规范中给出的参数,以及例子中的数据,我们进行一个校验。 CRC在线计算
图片里的ABCDEF与规范中的参数一一对应。 输入Autosar例子中的第一组数据,得出计算出来的结果与例子的一致。
四、CRC配置
4.1 Crc General
4.2 Crc Channels Configuration
五、Mcu
CRC时钟使能,如果选择Table计算的话,这里应该就不用配置了。如果选择硬件计算,那就要打开CRC的硬件时钟。
六、代码实现
6.1 代码实现
volatile uint32_t CrcResult1;
uint8 testdata1[3] = { 0xF2, 0x01, 0x83 };
CrcResult1 = Crc_CalculateCRC8(&testdata1[0], 3, 0U, TRUE);
6.2 Crc_CalculateCRC8函数讲解
uint8 Crc_CalculateCRC8(const uint8 *Crc_DataPtr, uint32 Crc_Length, uint8 Crc_StartValue8, boolean Crc_IsFirstCall)
参数1:要计算的数据源
参数2:计算几个字节的数据
参数3:start Value, 如果参数4为1,则忽略这个值。 如果参数4为0,那么计算的起始值则为这个数(这里看不懂没关系,下面会有例子详细的讲解)
参数4:True:第一次调用 FALSE: 后续调用
返回值: 计算的结果
这里使用autosar规范中例子2中数据参与计算,得出结果0x37,与规范一致。
函数Crc_CalculateCRC8()最终还是将要计算的数据,在下表中通过查表的方式计算出来。
Crc_lp_Lookup_Tables.c中:
6.3 Crc_CalculateCRC8参数3详解
6.3.1 参数4为TRUE
uint8 testdata1[3] = { 0xF2, 0x01, 0x83 };
CrcResult1 = Crc_CalculateCRC8(&testdata1[0], 3, 0U, TRUE);
CrcResult2 = Crc_CalculateCRC8(&testdata1[0], 3, 2U, TRUE);
当参数4为TRUE的时候,参数3的值是不起作用的,这时候上面计算出来的结果是一致的,如下:
6.3.2 参数4为FLASE
上面的例子跟计算结果好好地研究理解下,就能知道参数3跟4的用处了。
1:计算出table1的结果
2:计算出table2的结果
3:将table1和table2合在一起,生成table3,计算出table3的结果
4:计算出table3的前三个数据的结果,理论上跟1的结果一致
5:将参数4改为false, 参数3改为4的结果,那么就是将4的结果作为起始值,然后结算table3后四个数据的结果,理论上跟3出来的结果一致
6:6和5的区别就是参数4为false还是true, 证明了为true的时候,参数3不起作用。结果与2一致。