CAPL内置的与CRC有关函数

0、 参考文档

本文参考文档

  • CRC介绍部分: https://www.geeksforgeeks.org/modulo-2-binary-division/
  • 本文函数部分摘录自Vector的官方文档,做了整理与翻译,增加了自己的理解, 并将代码改造的更加优雅实用一些。

二、 CRC简介

CRC(Cyclic Redundancy Check)全称为:循环冗余校验,是一种常用的、具有检错、纠错能力的校验码。 用于检测通信信道(the communication channel) 中意外变化/错误的方法。

2.1 CRC基础知识

CRC使用**生成器多项式(Generator Polynomial) ** 来进行计算,它在发送方和接收方都可用。**生成器多项式(Generator Polynomial) ** 是一个极为重要的概念,它有两种不同的表示方法,举例说明:

  1. 一个示例生成器多项式 x3 + x + 1, 也可以表示为key: 二进制 1011
  2. 一个示例生成器多项式 x2 + 1, 也可以表示为key: 二进制 101

为了后续解释方便, 下面先定义nk两个变量,其含义如下:

n : Number of bits in data to be sent from sender side.  
k : Number of bits in the key obtained from generator polynomial.

为了简化说明,后面将所有的生成器多项式(Generator Polynomial) ** 称之为多项式(Polynomial)** , 实际项目中也经常这么表示。

2.2 发送方与接收方的处理数据过程

发送方, 根据原始数据和多项式(Polynomial), 也可以称之为密钥(key)生成用于传输的编码数据, 步骤如下:

  1. 首先在二进制数据的末尾添加上k-1个零来进行扩充, 形成一个新的二进制数
  2. 使用模2二进制除法(modulo-2 binary division) 将上一步生成的新二进制数据除以 key,并存储除法后的余数。
  3. 将余数附加在数据的末尾以形成编码数据并发送相同的数据

接收器侧(检查传输中是否引入错误)

  1. 再次执行模2除法(modulo-2 division) ,如果余数为0,则没有错误。

在本文中,我们将只关注查找余数(remainder) ,即检查字(check word)和码字(code word)。

2.2 模2除法(modulo-2 division)

模2除法(modulo-2 division) 介绍:

模2二进制除法(modulo-2 binary division) 的过程与我们熟悉的十进制除法过程相同。只是我们在这里使用XOR而不是减法(subtraction)

  1. 在每个步骤中,除数(或数据) 的一个副本与被除数(或密钥) 的k位进行异或(XORed)
  2. XOR运算(余数)的结果是(n-1)个比特,在将1个额外的比特拉低以使其变为n个比特长之后,将其用于下一步。
  3. 当没有剩余的部分可以下拉时,我们就有了结果。附加在发送方的(n-1)位余数。

原文:

  • In each step, a copy of the divisor (or data) is XORed with the k bits of the dividend (or key).
  • The result of the XOR operation (remainder) is (n-1) bits, which is used for the next step after 1 extra bit is pulled down to make it n bits long.
  • When there are no bits left to pull down, we have a result. The (n-1)-bit remainder which is appended at the sender side.

2.3 举例说明

2.3.1. 第一个例子,传输过程中没有错误产生

假设要发送的数据: 100100(0x24), 使用到的Key为1101(0xD), 或者说使用到的多项式(polynomial)为: x3 + x2 + 1, 计算过程如下:

请添加图片描述

从上面可以看到,余数(remainder) 为二进制的001,因此要发送的编码数据为二进制的 100100001

对于接收器侧来说:
接收端接收的数据为: 100100001, CRC校验部分计算过程如下:

请添加图片描述

从上面可以看到,余数(remainder) 都是零。因此,接收到的数据没有错误。

2.3.2. 第二个例子,传输过程中有错误产生

这个例子在发送方还是使用前面的例子:

假设要发送的数据: 100100, 使用到的Key为1101, 或者说使用到的多项式(polynomial)为: x3 + x2 + 1

然后,计算出来要发送的编码数据为二进制的 100100001

在这里,我们构造一个传输过程中出现错误,也就是构造一个错误的接收数字,假设接收端接收到的数据为二进制的100000001

在收到这个数字后,CRC校验部分计算过程如下:

请添加图片描述

从上面可以看到,由于余数(remainder) 不全为零,因此在接收器侧检测到错误。

2.4 其他CRC常用概念说明

上面部分介绍的CRC纯理论部分,实际使用时候还有很多新的概念。

2.4.1 宽度(Width)

指CRC校验码的宽度,同时也是指多项式的宽度。比如: crc-16的width是16,crc-32的宽度是32

下图摘自在线CRC计算网页, 这里列出了常见的CRC计算模型与其对应的多项式:

请添加图片描述

2.4.2 多项式(Poly)

指CRC校验的多项式的二进制码去掉最高位。
eg. crc8的Poly:gx=x8+x2+x1+1,二进制码100000111,所以POLY这个参数为:0x07

之所以去掉最高位,是因为最高位一直为1,所有进行了省略。 在很多实际使用场合中都省略了最高位。

2.4.3 初始值(Init)

是指CRC的寄存器的初始值.
eg.如为0xff,则INIT = 0xff; 如为0x0,则INIT = 0x00

如果初始值为(0x00),那么经过初始值异或运算后,被除数保持不变**(初始值的恒等率)** ; 也就是相当于加不加初始值都没有影响

2.4.4 输入值反转(RefIN)

是指需要校验的数据(输入值)二进制位数相反。
eg. 输入值为:10101100,则实际进行校验的值为00110101

2.4.5 输出值反转(RefOut)

指输出的校验码二进制位进行反转。
eg. 输出值为:10101100,则实际输出值为00110101

2.4.6 结果异或值(XorOut)

指运算出的校验码与结果异或值异或之后,最终最为校验码。
eg. XorOut为0xff,计算的校验码为0x17,则输出校验码为:0xff^0x17

三、 常见概念

上述介绍的是通用的CRC概念,但是在汽车领域,还有一些专用的与CRC有关的概念。

3.1 E2E概念

首先明确一点,**E2E(end to end)**并非只是在汽车领域应用,任何通信领域都会涉及,只不过是AutoSAR对这一协议/机制做了规范。

E2E,全称End to End,中文即端到端的通信保护,是一种针对安全相关数据,为防止通信链路中可能存在的故障(HW/SW), 在通信节点之间执行的 一种数据保护协议/机制。其适用于多种网络结构:CAN、 CANFD、FlexRay、Ethernet等。

3.2 AUTOSAR Profile 1

Profile 1 是 Legacy Profile,仅出于兼容性原因进行维护, 仅仅使用在CP中 。

MechanismDescription
Counter4bit (explicitly sent) representing numbers from 0 to 14 incremented on every send request. Both Alive Counter and Sequence Counter mechanisms are provided by E2E Profile 1, evaluating the same 4 bits.
Timeout monitoringTimeout is determined by E2E Supervision by means of evaluation of the Counter, by a nonblocking read at the receiver. Timeout is reported by E2E Supervision to the caller by means of the status flags in E2E_P01CheckStatusType.
Data ID16 bit, unique number, included in the CRC calculation. For dataIdMode equal to 0, 1 or 2, the Data ID is not transmitted, but included in the CRC computation (implicit trans- mission). For dataIdMode equal to 3: • the high nibble of high byte of DataID is not used (it is 0x0), as the DataID is limited to 12 bits, • the low nibble of high byte of DataID is transmitted explicitly and covered by CRC calculation when computing the CRC over Data. • the low byte is not transmitted, but it is included in the CRC computation as start value (implicit trans- mission, like for dataIDMode equal to 0, 1 or 2) .
CRCCRC-8-SAE J1850 - 0x1D (x8 + x4 + x3 + x2 + 1), but with different start and XOR values (both start value and XOR value are 0x00). This CRC is provided by CRC Supervision. Starting with AUTOSAR R4.0, the SAE8 CRC function of the CRC Supervision uses 0xFF as start value and XOR value. To compensate a different behavior of the CRC Supervision, the E2E Supervision applies additional XOR 0xFF operations starting with R4.0, to come up with 0x00 as start value and XOR value. Note: This CRC polynomial is different from the CRC- polynomials used by FlexRay, CAN and LIN.

E2E Profile 1应使用CRC-8-SAE J1850的多项式,即多项式为:x8+x4+x3+x2+1,但起始值(start value)XOR值等于 0x00

x8+x4+x3+x2+1即100011101,通常写为0x1D,注意这里不是0x11D,可能是最高位必然为1,所以省去了。

其他Profile参考: https://blog.csdn.net/qfmzhu/article/details/122334722

四、 介绍常用函数

CAPL中与CRC有关的函数如下:

FunctionsShort Description
Crc_CalculateCRC8根据数据计算CRC8 的相应校验和(checksum)
Crc_CalculateCRC8H2F根据数据计算CRC8H2F 的相应校验和(checksum)
Crc_CalculateCRC16根据数据计算CRC16 的相应校验和(checksum)
Crc_CalculateCRC32根据数据计算CRC32 的相应校验和(checksum)
Crc_CalculateCRC32P4根据数据计算CRC32P4 的相应校验和(checksum)
Crc_CalculateCRC64根据数据计算CRC64 的相应校验和(checksum)

补充说明:

Windows和Linux支持这些CAPL功能。Linux下的功能尚未经过全面测试。

4.1 函数: Crc_CalculateCRC8()

这里的CRC8计算方法在SAEJ1850 中定义。

函数语法
long Crc_CalculateCRC8 (BYTE* data, 
                        dword dataSize, 
                        dword dataOffset, 
                        dword crcLength, 
                        dword crcStartValue, 
                        dword firstCall, 
                        dword* crcCalculated);
函数功能描述

根据数据计算CRC8的相应校验和。CRC值的计算对应于AUTOSAR Profile 1

函数参数介绍
参数含义
dest要计算校验和的负载数据(Payload data)
dataSize要计算的数据块(data block)的长度(以字节为单位)
dataOffset用于计算负载数据(payload data)中的CRC的起始索引(Start index)
crcLength计算CRC的数据长度
crcStartValueCRC初始值取决于它是第一次调用还是后续调用。如果firstCall1 ,则忽略值。
firstCall第一次调用或后续调用的标志。可能的值为0(后续调用)1(第一次调用)
crcCalculated计算后的CRC8值
返回值介绍
返回值含义
0Successful
-1Not successful: CRC length must not be 0
-2Not successful: Offset must not be greater or equal length
-3Not successful: Length outside array range
-4Not successful: Summary of Length and offset are outside array range
举例说明

关于Crc_CalculateCRC8()函数说明的示例代码:

// first CALL, Offset '0'
on key 'a'
{
  long retval;
  dword crc;
  byte data[9] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};

  retval = Crc_CalculateCRC8(data, elcount (data), 0, elcount (data), 0, 1, crc);
  write("CRC of data: 0x%X", crc);
}

// first CALL, Offset '2', Length - 2
on key 'b'
{
  long retval;
  dword crc;
  byte data[11] = {0xAA ,0xAA,0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};

  retval = Crc_CalculateCRC8(data, elcount (data), 2, elcount (data) -2, 0, 1, crc);
  write("CRC of data: 0x%X", crc);
}

输出结果:

Data represents the number: Little Endian is used.

4.2 函数: Crc_CalculateCRC8H2F()

这里的CRC8H2F指的是: CRC8 0x2F polynomial

函数作用: 根据数据计算CRC8H2F的相应校验和。CRC值的计算对应于AUTOSAR Profile 2

函数语法
long Crc_CalculateCRC8H2F (BYTE* data, 
                           dword dataSize, 
                           dword dataOffset, 
                           dword crcLength, 
                           dword crcStartValue, 
                           dword firstCall, 
                           dword* crcCalculated);

函数的参数与返回值基本上等同于Crc_CalculateCRC8() 的说明,这里就不在赘述了。

举例说明

关于Crc_CalculateCRC8H2F()函数说明的示例代码:

// first CALL, Offset '0'
on key 'a'
{
  long retval;
  dword crc;
  byte data[9] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};

  retval = Crc_CalculateCRC8H2F(data, elcount (data), 0, elcount (data), 0, 1, crc);
  write("CRC of data: 0x%X", crc);
}

// first CALL, Offset '2', Length - 2
on key 'b'
{
  long retval;
  dword crc;
  byte data[11] = {0xAA ,0xAA,0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};

  retval = Crc_CalculateCRC8H2F(data, elcount (data), 2, elcount (data) -2, 0, 1, crc);
  write("CRC of data: 0x%X", crc);
}

4.3 函数: Crc_CalculateCRC16()

函数作用: 根据数据计算CRC16的相应校验和。CRC值的计算对应于AUTOSAR PROFILE_05PROFILE_06

函数语法
long Crc_CalculateCRC16 (BYTE* data, 
                         dword dataSize, 
                         dword dataOffset, 
                         dword crcLength, 
                         dword crcStartValue, 
                         dword firstCall, 
                         dword* crcCalculated);

函数的参数与返回值基本上等同于Crc_CalculateCRC8() 的说明,这里就不在赘述了。

举例说明

关于Crc_CalculateCRC16()函数说明的示例代码:

// first CALL, Offset '0'
on key 'a'
{
  long retval;
  dword crc;
  byte data[9] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};

  retval = Crc_CalculateCRC16(data, elcount (data), 0, elcount (data), 0, 1, crc);
  write("CRC of data: 0x%X", crc);
}

// first CALL, Offset '2', Length - 2
on key 'b'
{
  long retval;
  dword crc;
  byte data[11] = {0xAA ,0xAA,0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};

  retval = Crc_CalculateCRC16(data, elcount (data), 2, elcount (data) -2, 0, 1, crc);
  write("CRC of data: 0x%X", crc);
}

4.4 函数: Crc_CalculateCRC32()

函数作用: 根据数据计算CRC32的相应校验和。CRC值的计算对应于IEEE-802.3 CRC32

函数语法
long Crc_CalculateCRC32 (BYTE* data, 
                         dword dataSize, 
                         dword dataOffset, 
                         dword crcLength, 
                         dword crcStartValue, 
                         dword firstCall, 
                         dword* crcCalculated);

函数的参数与返回值基本上等同于Crc_CalculateCRC8() 的说明,这里就不在赘述了。

举例说明

关于Crc_CalculateCRC32()函数说明的示例代码:

// first CALL, Offset '0'
on key 'a'
{
  long retval;
  dword crc;
  byte data[9] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};

  retval = Crc_CalculateCRC32(data, elcount (data), 0, elcount (data), 0, 1, crc);
  write("CRC of data: 0x%X", crc);
}

// first CALL, Offset '2', Length - 2
on key 'b'
{
  long retval;
  dword crc;
  byte data[11] = {0xAA ,0xAA,0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};

  retval = Crc_CalculateCRC32(data, elcount (data), 2, elcount (data) -2, 0, 1, crc);
  write("CRC of data: 0x%X", crc);
}

4.5 函数: Crc_CalculateCRC32P4()

这里的CRC32P4 指的是: CRC32 0x1F4ACFB13 polynomial

函数作用: 根据数据计算CRC32P4的相应校验和。CRC值的计算对应于AUTOSAR Profile 4

函数语法
long Crc_CalculateCRC32P4 (BYTE* data, 
                           dword dataSize, 
                           dword dataOffset, 
                           dword crcLength, 
                           dword crcStartValue, 
                           dword firstCall, 
                           dword* crcCalculated);

函数的参数与返回值基本上等同于Crc_CalculateCRC8() 的说明,这里就不在赘述了。

举例说明

关于Crc_CalculateCRC32P4()函数说明的示例代码:

// first CALL, Offset '0'
on key 'a'
{
  long retval;
  dword crc;
  byte data[9] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};

  retval = Crc_CalculateCRC32P4(data, elcount (data), 0, elcount (data), 0, 1, crc);
  write("CRC of data: 0x%X", crc);
}

// first CALL, Offset '2', Length - 2
on key 'b'
{
  long retval;
  dword crc;
  byte data[11] = {0xAA ,0xAA,0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};

  retval = Crc_CalculateCRC32P4(data, elcount (data), 2, elcount (data) -2, 0, 1, crc);
  write("CRC of data: 0x%X", crc);
}

4.6 函数: Crc_CalculateCRC64()

函数作用: 根据数据计算CRC64的相应校验和。CRC值的计算对应于 AUTOSAR Profile 7

函数语法
long Crc_CalculateCRC64 (BYTE* data, 
                         dword dataSize, 
                         dword dataOffset, 
                         dword crcLength, 
                         qword crcStartValue, 
                         dword firstCall, 
                         qword* crcCalculated);

函数的参数与返回值基本上等同于Crc_CalculateCRC8() 的说明,这里就不在赘述了。

举例说明

关于Crc_CalculateCRC64()函数说明的示例代码:

	
// first CALL, Offset '0'
on key 'a'
{
  long retval;
  qword crc;
  byte data[9] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};

  retval = Crc_CalculateCRC8(data, elcount (data), 0, elcount (data), 0, 1, crc);
  write("CRC of data: 0x%X", crc);
}

// first CALL, Offset '2', Length - 2
on key 'b'
{
  long retval;
  qword crc;
  byte data[11] = {0xAA ,0xAA,0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};

  retval = Crc_CalculateCRC8(data, elcount (data), 2, elcount (data) -2, 0, 1, crc);
  write("CRC of data: 0x%X", crc);
}
  • 4
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
crc8校验的原理,程序和检验软件 CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。 CRC校验可以简单地描述为:例如我们要发送一些数据(信息字段),为了避免一些干扰以及在接收端的对读取的数据进行判断是否接受的是真实的数据,这时我们就要加上校验数据(即CRC校验码),来判断接收的数据是否正确。在发送端,根据要传送的k位二进制码序列,以一定的规则(CRC校验有不同的规则。这个规则,在差错控制理论称为“生成多项式”。)产生一个校验用的r位校验码(CRC码),附在原始信息后边,构成一个新的二进制码序列数共k+r位,然后发送出去。在接收端,根据信息码和CRC码之间所遵循的规则(即与发送时生成CRC校验码相同的规则)进行检验,校验采用计算机的模二除法,即除数和被除数(即生成多项式)做异或运算,进行异或运算时除数和被除数最高位对齐,进行按位异或运算,若最终的数据能被除尽,则传输正确;否则,传输错误。 CRC8即最终生成的CRC校验码为1字节,其生成多项式,生成多项式为g(x)=x8+x5+x4+1,相当于g(x)=1•x8+0•x7+0•x6+1•x5+1•x4+0•x3+0•x2+0•x1+1•x0,即对应的二进制数为100110001。 CRC8校验算法: 1.CRC8校验的一般性算法: 例如: 信息字段代码为: 00000001 00000010 ———— 对应m(x)=x8+x 生成多项式为:g(x)=x8+x5+x4+1 ———— 对应g(x)的二进制代码为:100110001 现在我们将要对2字节数据0x0102生成CRC8校验码,并最终将生成的1字节CRC校验码跟在0x0102的后面,即 0x01 02 ##,(##即8为CRC码),最终生成的3字节数据就是经CRC8校验生成的数据。 先计算x8m(x)=x16+x9,对应的2进制数为:100000010 00000000 。可以看到这样运算所得到的结果其实就是将信息字段代码的数左移8位。因为最终要将生成的8位CRC8校验码附在信息字段的后面,所以要将信息字段的数左移8位。最后用x8m(x)得到的二进制数对生成多项式g(x)进行模二运算,最终的余数(其二进制数的位数一定比生成多项式g(x)的位数小)就是所要的CRC8校验码。 100000010 00000000 ^ 100110001 --------------------------- 000110011 00000000 ^ 100110 001 --------------------------- 010101 00100000 ^ 10011 0001 --------------------------- 00110 00110000 ^ 100 110001 --------------------------- 010 11110100 ^ 10 0110001 --------------------------- 00 10010110 对x8m(x)做模二运算取余得10010110(0x96),这个8位的二进制数就是CRC8校验码。所以,经CRC8校验后研发送的数据就是0x010296。 2.CRC8校验在DS18B20的应用: 以上分析的是常规的CRC8校验方法。在DS18B20,有两处用到CRC。一是DS18B20的8字节的序列号,最后一字节是前面七个字节的CRC码,这是为了保证序列号的唯一性与正确性;另一个是在DS18B20内部9字节的高速温度存储器,其第9字节是前面8个字节的CRC校验码,这是为了温度数据传输的正确性。而在DS18B20生成CRC码所用到的方法不同于常规生成算法,它采用的是逆序CRC信息单元编码算法,该CRC的生成是由DS18B20的多项式寄存器通过其所包含的移位寄存器以及异或门对输入该多项式寄存器的每一位二进制数做一定的运算所得到的CRC码(可以查看Maxim官网上DS18B20的应用笔记Note27,专门介绍DS18B20CRC详细生成过程)。在此列举两种DS18B20CRC校验的C程序。
As an AI language model, I do not have access to the specific requirements or details for the E2E_CalculateCRC8 function. However, I can provide a general explanation of what a CRC8 calculation is and how it can be implemented. CRC (Cyclic Redundancy Check) is a type of error-detecting code used in digital communication systems to detect accidental changes to raw data. A CRC8 checksum is a specific type of CRC that uses an 8-bit polynomial to generate the checksum value. The checksum is calculated by dividing the raw data by the polynomial and taking the remainder as the checksum value. To implement a CRC8 calculation, the following steps can be taken: 1. Define the polynomial used for the CRC8 calculation. This is typically an 8-bit value such as 0x07 or 0x9B. 2. Initialize a variable to hold the current checksum value. This is typically set to 0xFF. 3. For each byte of data in the input message, XOR it with the current checksum value and update the checksum value using the polynomial. 4. After processing all the bytes in the input message, the final checksum value is the CRC8 checksum. Here is an example implementation of a CRC8 calculation in C: ``` #define CRC8_POLYNOMIAL 0x07 unsigned char calculate_crc8(unsigned char *data, unsigned int length) { unsigned char crc = 0xFF; unsigned int i, j; for (i = 0; i < length; i++) { crc ^= data[i]; for (j = 0; j < 8; j++) { if (crc & 0x80) { crc = (crc << 1) ^ CRC8_POLYNOMIAL; } else { crc <<= 1; } } } return crc; } ``` This function takes an input message as an array of bytes and its length as an integer. It returns the calculated CRC8 checksum as an unsigned char value. The function performs the XOR and polynomial operations on each byte of the input message to calculate the checksum value.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值