0


CRC-8校验算法与CAN知识

文章目录

A.1 CRC8 算法

A.1.1 CRC8 算法参数设置

CRC8 算法中要求了 Counter、Data ID、CRC 等参数设置。
参数描述Counter共 4bits,在 CAN 总线通信时,从 0-15 滚动发送。Message ID共 16bits(在 ID 前用 ‘0’ 填充后),总线报文 ID,在进行 CRC 计算时应包含。CRC共 8bits,CRC 算法参照 SAE J1850,生成多项式为0x1D(x8+x4+x3+x2+1),但初始值和 XOR 值均替换为0x00,在 CAN 总线上发送

A.1.2 Counter

在 CRC8 算法中,发送方在第一次发送时将 Counter 置为 0,并在后续每次发送时将
Counter 加 1。当 Counter 值达到 15(0xF)后,发送方的下一次发送将 Counter 重新置为0。
接收节点在接收到报文后对 Counter 值进行监控:
a)连续接收到 4 个周期 Counter 值相同时不计为错误,但在随后第 5 个周期中 Counter
值仍相同时,需记录 Counter 错误;
b)当连续接收到连续 3 个周期的 Counter 差值≥2 时,需记录 Counter 错误;
当检查到 Counter 错误时,将使用信号定义的 Invalid 值或替代值,直到 Counter 值恢复连续为止。

A.1.3 Message ID

在 CRC8 算法中,Message ID( 在 ID 前用 ‘0’ 填充)的 2 个字节(16bits)都会包含在 CRC计算中。在计算时,将 Data ID 加入在需保护数据之前。

A.1.4 CRC

在 CRC8 算法中,CRC 计算使用了 SAE J1850,生成多项式为 0x1D(x8+x4+x3+x2+1) ,但初始值和 XOR 值均替换为 0x00。*

(Autosar E2E profile 1 规定采用CRC-8-SAE J1850 ,对应多项式 [公式] ,即100011101,通常写为0x1D,注意这里不是0x11D,最高位为1省去了。)*

在 CRC 计算时,计算示例见图 1
a)首先计算 Message ID 的两个字节,先 高字节 后 低字节 ;
b)其次计算在总线上发送的需要保护的信号/信号组(不包含 CRC 字段)
在这里插入图片描述

A.1.5 CRC8 算法示例

a)报文 ID(Msg ID):0x345
b)需保护的数据(Protected Data):0x11 0x22 0x33 0x44 0x55 0x66 0x77
c)CRC8_Checksum = CRC8(0x03 0x45 0x11 0x22 0x33 0x44 0x55 0x66 0x77)
d)CRC8_checksum = 0x15 

A.1.6 CRC8 算法推荐

/*定义 CRC8(计算规则 0x1D)的查表的表格*/const uint8_t crc_table[256]={0x00,0x1D,0x3A,0x27,0x74,0x69,0x4E,0x53,0xE8,0xF5,0xD2,0xCF,0x9C,0x81,0xA6,0xBB,0xCD,0xD0,0xF7,0xEA,0xB9,0xA4,0x83,0x9E,0x25,0x38,0x1F,0x02,0x51,0x4C,0x6B,0x76,0x87,0x9A,0xBD,0xA0,0xF3,0xEE,0xC9,0xD4,0x6F,0x72,0x55,0x48,0x1B,0x06,0x21,0x3C,0x4A,0x57,0x70,0x6D,0x3E,0x23,0x04,0x19,0xA2,0xBF,0x98,0x85,0xD6,0xCB,0xEC,0xF1,0x13,0x0E,0x29,0x34,0x67,0x7A,0x5D,0x40,0xFB,0xE6,0xC1,0xDC,0x8F,0x92,0xB5,0xA8,0xDE,0xC3,0xE4,0xF9,0xAA,0xB7,0x90,0x8D,0x36,0x2B,0x0C,0x11,0x42,0x5F,0x78,0x65,0x94,0x89,0xAE,0xB3,0xE0,0xFD,0xDA,0xC7,0x7C,0x61,0x46,0x5B,0x08,0x15,0x32,0x2F,0x59,0x44,0x63,0x7E,0x2D,0x30,0x17,0x0A,0xB1,0xAC,0x8B,0x96,0xC5,0xD8,0xFF,0xE2,0x26,0x3B,0x1C,0x01,0x52,0x4F,0x68,0x75,0xCE,0xD3,0xF4,0xE9,0xBA,0xA7,0x80,0x9D,0xEB,0xF6,0xD1,0xCC,0x9F,0x82,0xA5,0xB8,0x03,0x1E,0x39,0x24,0x77,0x6A,0x4D,0x50,0xA1,0xBC,0x9B,0x86,0xD5,0xC8,0xEF,0xF2,0x49,0x54,0x73,0x6E,0x3D,0x20,0x07,0x1A,0x6C,0x71,0x56,0x4B,0x18,0x05,0x22,0x3F,0x84,0x99,0xBE,0xA3,0xF0,0xED,0xCA,0xD7,0x35,0x28,0x0F,0x12,0x41,0x5C,0x7B,0x66,0xDD,0xC0,0xE7,0xFA,0xA9,0xB4,0x93,0x8E,0xF8,0xE5,0xC2,0xDF,0x8C,0x91,0xB6,0xAB,0x10,0x0D,0x2A,0x37,0x64,0x79,0x5E,0x43,0xB2,0xAF,0x88,0x95,0xC6,0xDB,0xFC,0xE1,0x5A,0x47,0x60,0x7D,0x2E,0x33,0x14,0x09,0x7F,0x62,0x45,0x58,0x0B,0x16,0x31,0x2C,0x97,0x8A,0xAD,0xB0,0xE3,0xFE,0xD9,0xC4};4/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * crc_table[256]表中参数是{0...255}中每个元素与OX1D异或的结果******
* * CRC8 校验子程序 0x1D(x8+x4+x3+x2+1) * * * * * * * * * * * *
* * 参数 1,uint8_t *data:需要计算的数据 * * * * * * * * * * *
* * 参数 1,uint16_t len:需要计算的数据字节长度 * * * * * * * *
* * 返回值,uint8_t crc8:计算出的 CRC 值 * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint8_t crc_8find(uint8_t *data, uint16_t len){
 uint8_t crc8 =0x00;while( len--){
 crc8 = crc_table[crc8 ^*data];
 data++;}return crc8;}

附手写计算图片:在这里插入图片描述

A.1.7 CRC8 算法示例实操

下边是C代码实现部分,可以看出每计算一个byte移位8次,如果考虑运行速度的话可以提前计算出0x00-0xFF每一个数据对应的CRC先放好,然后再查表,这就是上面推荐的CRC方法(

查表法

)。
下面我们用异或的方式计算:

unsignedcharmyCRC8(unsignedchar pData[],int len){unsignedchar u8Crc;int i;int j;    
    u8Crc =0;//一个字节均为0for(i=0; i<len; i++)//字节循环{  
    u8Crc ^= pData[i];//与0异或是自己本身,取得第一个字节for(j=0;j<8;j++)//计算循环{if(u8Crc &0x80)//判断高位是否为1{
            u8Crc <<=1;//对齐与0x11D,低位补0
            u8Crc ^=0x1D;//Autosar profile 1.原为0X11D舍弃了高位1}else{
            u8Crc <<=1;//左移一位}}}
    u8Crc ^=0;//与0异或是自己本身return u8Crc;//传回CRC}intmain(){unsignedchar Crc;unsignedchar data[9]={0x030x450x110x220x330x440x550x660x77};      
    Crc =myCRC8(data,9);//传入参数到函数  printf("Crc=0x%x---%d",Crc,Crc);return0;}

验证计算是否正确可以在网站上搜索CRC在线计算:
在这里插入图片描述

A.1.8 CAN有关小知识

缩写全称LSBleast significant byteMSBmost significant bytelsbleast significant bitmsbmost significant bit
在这里插入图片描述

CAN报文数据域传输顺序:
字节顺序:先传Byte0(LSB),最后传Byte7(MSB);
字节内位序:先传bit7(lsb),最后传bit0(msb);

当信号在一个字节内实现(信号不跨字节)时,Intel模式和Motorola模式的信号字节顺序,完全一样:
**

信号的高位(MSB)放在该字节的高位,信号的低位(LSB)放在该字节的低位。

**
在这里插入图片描述

当信号在多个字节内实现(信号跨字节)时,Intel模式和Motorola模式的信号字节顺序,明显不同:
**

Intel模式:信号的高位(MSB)放在高字节的高位,信号的低位(LSB)放在低字节的低位;

**
在这里插入图片描述

**

Motorola模式:信号的高位(MSB)放在低字节的高位,信号的低位(LSB)放在高字节的低位。

**
在这里插入图片描述

俗称:小端模式

“高在后,低在前”

;大端模式

“高在前,低在后”

。不管Intel模式,还是Motorola模式,起始位都该信号的低位(lsb)。
高八位、低八位在这里插入图片描述

高八位:10101100 
G=(AC47>>8)&0XFF
低八位:01000111
D=AC47&0XFF

高四位、低四位
在这里插入图片描述

高四位:1101
G=D4&0XF0
低四位:0100
D=D4&0X0F

A.1.9 附加小知识

两个数组合并一个数组输出

#include<stdio.h>intmain(){int i;int j=0;unsignedchar A[7]={0x11,0x22,0x33,0x44,0x55,0X66,0x77};int p;
p=0x345;unsignedchar C[9];
C[0]=((p>>8)&0xFF);
C[1]=(p &0xFF);//for(i=0;i<7;i++){
        C[j+2]=A[i];
        j++;}//C[j]='\0'; for(i=0;i<9;i++){printf("C=%x",C[i]);printf("\n");}return0;}
标签: c语言 安全

本文转载自: https://blog.csdn.net/weixin_45403142/article/details/123566592
版权归原作者 SDK.Paraman 所有, 如有侵权,请联系我们删除。

“CRC-8校验算法与CAN知识”的评论:

还没有评论