autosim 发表于 2021-11-1 15:39:58

SAE-J1850汽车CAN总线CheckSum算法之CRC-8校验算法

CRC(Cyclic Redundancy Check),循环冗余校验

CRC算法将数据与多项式相除,得到的余数再与多项式相除,如此反复,所以叫循环冗余,最终得到一个和多项式位数相同的余数,作为校验码;

多项式决定了校验码的位数,根据校验码位数不同,一般有CRC-4,CRC-8,CRC-16,CRC-32,CRC-64,CRC-128等,不同的多项式对错误的检测率有差别,CRC相关标准中推荐的多项式都是精心挑选的。

SAE-J1850中的CRC-8校验算法

SAE-J1850中推荐的CRC校验多项式为1Dh, 即:x^8+x^4+x^3+x^2+1;

多项式的最高位默认均为1,且在CRC-8算法中,最高位不使用,因此在多项式记录时去掉了最高位;

1Dh转化为二进制为11101b,最高位补1后为10011101b,二进制中的每一位,对应多项式中的系数;

SAE-J1850中的CRC-8算法被AUTOSAR标准所引用,后者还推荐了另外一种多项式为2Fh(x^8+x^5+x^3+x^2+x^1+1)的CRC-8校验算法。

参见:https://www.autosar.org/fileadmin/user_upload/standards/classic/4-3/AUTOSAR_SWS_CRCLibrary.pdf

SAE-J1850中的CRC-8校验算法嵌入式代码实现(C语言)

u8 crc8(u8 *data, u8 length)                        //SAE-J1850 CRC-8 function
{
      u8 t_crc;
      u8 f, b;
      t_crc = 0xFF;
      for (f = 0; f < length; f++)
      {
                t_crc ^= data;
                for (b = 0; b < 8; b++)
                {
                        if ((t_crc & 0x80) != 0)                        //最高位为1,需要异或
                        {
                              t_crc <<= 1;
                              t_crc ^= 0x1D;
                        }
                        else
                        {
                              t_crc <<= 1;
                        }
                }
      }
      return ~t_crc;                        //按位非,相当于异或0xFF
}

上述0xFF、0x1D、0xFF分别对应SAE-J1850中规定的Polynomial、Initial value、XOR value,如下图所示:



在线验证CRC-8校验算法有效性

推荐一个可以在线运行C代码的网页:https://c.runoob.com/compile/11/

使用SAE-J1850中的示例,0x0F 0xAA 0x00 0x55,CRC为0x79;

验证代码如下:

#include <stdio.h>
typedef unsigned char u8;
u8 crc8(u8 *data, u8 length)
{
      u8 t_crc;
      u8 f, b;
      t_crc = 0xFF;
      for (f = 0; f < length; f++)
      {
                t_crc ^= data;
                for (b = 0; b < 8; b++)
                {
                        if ((t_crc & 0x80) != 0)
                        {
                              t_crc <<= 1;
                              t_crc ^= 0x1D;
                        }
                        else
                        {
                              t_crc <<= 1;
                        }
                }
      }
      return ~t_crc;
}
int main()
{
      u8 data={0x0F, 0xAA, 0x00, 0x55};
      u8 length=4;
      u8 t_crc;
      t_crc=crc8(data,length);
      printf("\r\nCRC8=%02X\r\n", t_crc);
}
页: [1]
查看完整版本: SAE-J1850汽车CAN总线CheckSum算法之CRC-8校验算法