现在在一辆汽车上,有很多控制器,很多控制器之间的通讯需要通过CAN网络,通讯过程中数据的传输尤为重要,因为数据的交互之后往往伴随着相关的硬件会执行指令的请求。在这个过程中,数据的检验是非常有必要的,checksum就是用来校验数据的一致性,主要是输入和输出的数据。
checksum算法多种多样,可以根据客户的提供的算法当然也可以自己按照软件的需求进行开发,这里我们说下比较简单的一种算法,checksum累加和的计算。
发送方:
1.计算checksum的数据按1byte划分开来,每1byte组成一个8bit的值(即抓取一段报文)
2.将所有的1字节8位的值进行累加得到一个新值
3.若新的值溢出了,即大于0xff时,将新值得高8位与低8位进行相加
4.将最终的8位的值进行按位求反,及得到了checksum的值
接收方:
可以将发送端的数据与checksum的值进行相加,理论上相加后的值按位都为1,此时将该值再加1,得到的结果为0(实际得到的应该是0b100000000,但是由于是使用unsigned char(8位)来保存累加和,所以高位被截取掉,只剩下了低八位的8个0).那么说明数据没有出现传输错误
假设有一段发送报文为:03 33 32 00 0E 00 04 00
累加:0x03+0x33+0x32+0x0E+0x04 = 0x7B
取反:为0x84
接收方:0x03+0x33+0x32+0x0E+0x04 +0x84 = 0xff
(uint8)0xff +0x01 = 0
发送:
uint8_t Send_CheckSum(uint8_t *data, uint8_t len) //data为数组,len为数组长度
{
uint8_t i, crc = 0;
for(i=0; i
crc += *(data++);
}
crc = ~crc;
return crc;
}
接收:
uint8_t receive_CheckSum(uint8_t *data, uint8_t len) //data为数组,len为数组长度
{
uint8_t i, crc = 0;
for(i=0; i
crc += *(data++);
}
crc = crc;
return crc+1;
}
也是将checksum的数据按1byte划分开来,每1byte组成一个8bit的值
算法:按报文信息的地址(按1字节划分)再加上报文的前7字节的和,高位溢出取低8位。
举例说明:若某报文的地址为0x284,某信号报文内容为:00 00 FF FF 00 00 9A 1E
累加:0x02+0x84+0xFF+0xFF+0x9A = 0x31E 高位溢出了3,舍掉取低8位
crc = 1E
代码实现:
can_crc.c
#include "can_crc.h"
uint8 CRC8_SAE_CksIdx(const uint8 *xData,uint8 xDataLen,uint8 id1,uint8 id2)
{
uint8 crc = (CRC_INIT1 + id1 + id2);
uint8 u8ByteIdx;
for ( u8ByteIdx=0 ; u8ByteIdx<=(xDataLen-1); u8ByteIdx++ )
{
crc += xData[u8ByteIdx];
}
return crc&UINT8_MAX;
}
can_crc.h
#include "std_type.h"
#define UINT8_MAX 0xFF
#define CRC_POLY 0x1D // Polynom = 0x1D
#define CRC_INIT 0xFF // init value = 0xFF
#define CRC_INIT1 0x00 // init value = 0x00
#define CKS_LASTB 7// CheckSum at last byte in the message
extern uint8 CRC8_SAE_CksIdx(const uint8 *xData,uint8 xDataLen,uint8 id1,uint8 id2);