CAN通信基础:CRC校验在CAN通信中的应用

1 CRC算法基础

1.1 简介

CRC(循环冗余校验,Cyclic Redundancy Check)是一种常用的、基于多项式除法的校验方法,用于检测数据传输或存储过程中的错误。

基本原理

  • CRC算法将数据视为多项式,并将数据多项式除以一个收发双方约定的多项式(称为生成多项式),计算得到的余数就是CRC校验值;
  • 生成的余数(CRC校验值)会被附加至原始数据后面,随原始数据一同发送或存储;
  • 当数据被接收时,接收方会使用相同的生成多项式对数据进行CRC计算。如果计算出的CRC值与接收到的CRC值相匹配,那么数据被认为是正确的;如果不匹配,数据在传输或存储过程中可能发生了错误。

算法参数
通常,CRC算法需要明确如下参数:

  • 生成多项式:决定了CRC算法的特性,不同的多项式会产生不同的CRC算法。
  • 初始值:CRC计算开始前寄存器的初始值。
  • 输入数据反转:部分CRC算法在处理数据前会反转数据的位顺序。
  • 输出数据反转:部分CRC算法在输出CRC值前会反转CRC值的位顺序。
  • 最终XOR值:CRC计算完成后,与CRC寄存器的最终值进行XOR操作的值。

优势和应用

  • CRC校验能够检测出所有奇数个错误和几乎所有的偶数个错误,以及所有长度小于或等于生成多项式次数的突发错误。
  • CRC校验的计算效率高,适合硬件和软件实现。
  • CRC校验广泛应用于通信领域,用于确保数据的完整性和准确性。在CAN协议中,数据链路层使用CRC-15校验CAN帧的准确性;应用层也常常在重要报文中添加Checksum信号(基于CRC-8)校验CAN数据的准确性。

1.2 CRC的生成多项式

首先,对CRC校验中生成多项式进行介绍。
CRC算法的多项式可以通过二进制序列表示。如某CRC-8算法的二进制表示为1 0001 1101,最低位(右1位)是第0比特,其多项式 P ( x ) = x 8 + x 4 + x 3 + x 2 + 1 P(x)=x^8+x^4+x^3+x^2+1 P(x)=x8+x4+x3+x2+1 与二进制序列一一对应。由于CRC-8生成多项式最高位阶指数默认是8,则最高位通常不表示,则上述CRC-8生成多项式常用十六进制1Dh表示。

1.3 CRC运算示例和多项式除法(模2除法)

CRC校验方法使用多项式除法(模2除法) 进行计算,下面以具体实例说明模2除法如何计算CRC校验值。

现有数据FFh(1111 1111)使用CRC-8 1Dh进行校验。其计算CRC校验码的过程如下:

  • CRC-8 1Dh算法的生成多项式为 P ( x ) = x 8 + x 4 + x 3 + x 2 + 1 P(x)=x^8+x^4+x^3+x^2+1 P(x)=x8+x4+x3+x2+1 ,其对应的二进制序列为100011101;
  • 在原始数据FFh(1111 1111)补充8位的数据0,其中8是生成多项式的阶数;
  • 使用补0之后的二进制数据对生成多项式的二进制序列进行模2运算(见下图)。其实际计算方式是从数据最高位开始和生成多项式进行异或运算,不断向数据低位滑动;
  • 最终得到余数C4h(1100 0100),当不足8位时,需要高位补零得到8比特的CRC校验码。
    模2除法

2 CAN数据链路层的CRC Field

ISO 11898-1协议为CAN数据帧定义CRC字段:

  • 该CRC字段长度为15比特;
  • 该CRC生成多项式为 P ( x ) = x 15 + x 14 + x 10 + x 8 + x 7 + x 4 + x 3 + 1 P(x)=x^{15}+x^{14}+x^{10}+x^8+x^7+x^4+x^3+1 P(x)=x15+x14+x10+x8+x7+x4+x3+1
  • 该CRC校验数据的范围是SOF(Start of Frame,帧起始)字段至Data Field(数据域)结束;
  • 若某接收节点计算的CRC字段与其接收到的CRC字段数值不一致,则会在ACK-DEL(ACK字段界定符)之后发出错误帧。

CAN Data Frame


3 CAN报文的Rolling Counter和Checksum

为了提高CAN通信传输的可靠性,重要的CAN报文通常需要包含Rolling Counter和Checksum两个信号。如下图,是常见的Rolling Counter和Checksum的在一帧CAN报文中的布局。Rolling Counter和Checksum


3.1 Rolling Counter

Rolling Counter是CAN报文的滚动计数器,用于跟踪报文的序列,确保报文按预期顺序接收。它是一个简单的递增计数器,范围为0-15之间递增循环。通常以一个4比特长度Singal的形式体现。Rolling Counter可以帮助接收方应用软件判断:报文传输过程中是否出现丢帧和乱序。


3.2 Checksum

Checksum是一种CAN报文的数据校验码,用于检查通信数据的完整性。Checksum在CAN报文中通常以一个8比特长度信号的形式体现,常用CRC-8算法。Checksum信号中是发送方按照算法计算出的校验码,其校验范围是本条CAN报文中的其他信号。接收方收到CAN报文后,会根据同样的算法计算校验码,并与Checksum信号进行对比,若两者一致,则认为报文传输过程未出现错误。

在CAN通信设计中,需要约定系统中所有CAN控制器使用的Checksum校验算法,供应商按照此算法实现控制器。下表是CRCH1D算法的参数,以此算法为例介绍发送方和接收方需要约定的CRC8算法参数。

算法参数数值解释
宽度 Width8 BitsCRC-8算法计算结果的宽度是8比特
生成多项式 Polynomial1Dh发送、接收双方约定的计算CRC校验值的多项式
初始值 Initial ValueFFhCRC寄存器的初始值
输入数据反转 Input Data ReflectedNO输入数据是否进行反转
输出数据反转 Output Data ReflectedNO输出数据是否进行反转
异或值 XOR ValueFFh输出数据与此值进行异或计算
校验值 Check4Bh用户在指定一段数据,此段数据进入校验后的数值。
魔术校验值 Magic CheckC4h详见解释

解释

  • 生成多项式:CRC-8算法的多项式可以通过十六进制表示。如1Dh的二进制表示为0001 1101,CRC-8第一位默认隐藏,故实际多项式二进制序列为(1) 0001 1101。按照二进制序列对应 x x x 的指数,则生成多项式 P ( x ) = x 8 + x 4 + x 3 + x 2 + 1 P(x)=x^8+x^4+x^3+x^2+1 P(x)=x8+x4+x3+x2+1
  • 初始值:初始值是在开始CRC计算之前,CRC寄存器被设置的值;
  • 输入数据反转:在进行CRC计算之前,输入数据的位不会被反转。该反转指位反转,即1101位反转后为1011;
  • 输出数据反转:在进行CRC计算之后,输出数据的位不会被反转;
  • 异或值:XOR值是在CRC计算完成后,与CRC寄存器的最终值进行XOR(异或)操作的值;
  • 校验值:用户指定一段输入数据,经过此CRC算法校验后的输出值。如使用ASCII值’1’,‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, '9’作为输入数据,输出得到的校验值;
  • 魔术校验值:任意一段数据经过CRC校验后,得到CRC校验值。将CRC校验值附加于原数据后形成新的输入数据,并进行CRC校验,得到的校验值与异或值(XOR Value)异或,最终输出魔术校验值(Magic Check)。此数值不受原始数据影响,任意数据经过此过程后可得到唯一的魔术校验值。

4 CRC算法代码实现

# python
def crc8h1d(ptr, length):  
    crc = 0xFF          # [参数]初始值 Initial Value : 0xFF
    polynomial = 0x1D   # [参数]生成多项式  Polynomial = P(x)=x^4+x^3+x^2+1  
    for i in range(length):     # 读入数据  
        crc ^= ptr[i]           # 数据与当前CRC寄存器中的数值进行异或  
        for j in range(8):      # 逐位处理 模拟模2除法  
            if (crc & 0x80):    # 当前高位是1,则左移1位并异或生成多项式(模2除法):左移1位的原因是当前生成多项式表达式不包含最高次幂  
                crc = ((crc << 1) ^ polynomial) & 0xFF  
            else:               # 当前高位是0,则左移1位  
                crc = (crc << 1) & 0xFF  
            crc &= 0xFF         # [参数]宽度  Width : 8 bits  
    return crc ^ 0xFF           # [参数]最终异或值 XOR Value : 0xFF  
  
ptr = [0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39]  # 输入数据(此输入数据为计算Check值的输入)
length = 9  # 输入数据长度  
  
crc_value = crc8h1d(ptr, length)                # 计算CRCH1D校验值  
print(f"The CRC value is: {crc_value:#04x}")    # The CRC value is: 0x4b

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值