Autosar BSW层CAN通讯开发------08(Autosar的E2E开发-----以E2E Profile01为例)

article/2025/10/17 2:38:18

Crc校验在CAN报文中的实际应用介绍:

        Crc在报文传输过程中的实际应用如下(在汽车中,Crc一般是对8个字节进行校验,目前我接触到的是这样):

        ECU-A和ECU-B之间进行CAN报文的传输,双方规定ECU-A发出的0x123报文为64个字节,该报文中的Byte1-Byte7要进行Crc校验,校验结果放到Byte0中,Alivecounter为Byte7的低四位(范围为0-14)。其余的Byte8-Byte64不进行校验。校验范围如下图所示

        因此,ECU-A往CAN总线发出这帧报文之前,要对每帧报文的Alivecounter按照0-14进行不断自增、循环。然后进行Crc校验并把校验结果存放到这帧报文的Byte0中,最后通过CAN总线发出这帧报文数据。

        ECU-B接收到这帧报文后,由于Byte8-Byte64不在校验范围内,因此接收到这帧报文后这个范围内的数据可以直接使用。但Byte0-Byte7为校验范围,因此ECU-B按照双方规定好的Crc算法对Byte1-Byte7进行校验,校验结果跟接收到的Byte0进行对比,若对比结果一致,则使用这帧报文的Byte1-Byte7的数据,否则丢弃这些数据。

        这就是Crc算法在CAN报文中的具体使用。


E2E和Crc的区别

        接下来就是Autosar的E2E(End-to-End,可以理解为数据从一个ECU传到另一个ECU)。

        刚开始接触的时候,我总没搞明白所谓的E2E和CRC到底有啥区别,因为在开发过程中,只关心两件事:Checksum计算是否正确、Counter的值是否按照要求进行递增并循环。

        后来在不断的学习和深入开发的才知道:

        Crc仅仅是一个校验算法

        E2E是Autosar官方定义的标准,它包含了Crc算法、要求了Counter的值如何进行递增、并在Counter出错时会记录对应的错误状态等等。


        讲完了上面这些东西,你应该对E2E有一个最简单的了解了。概况来说,其实就是校验。但Autosar标准定义的E2E并没有那么简单。下面,我用开发一帧接收报文的E2E功能慢慢来讲(发送的没啥讲的,就是发送前填充一下Checksum和Counter的值)。

        需求:对接收到的长度为8个Byte的0x1AA报文开发E2E功能。

        告诉你这个之后,还必须告诉你一些E2E的具体需求,没有这些你是无法开发的。(因为汽车上多个节点进行通讯,如果使用E2E功能的话,那么必须各个节点E2E需求保持一致,否则各个节点用的算法都不一样,这还校个啥。)

        好了,E2E的具体需求释放给你了,如下:

               算法:使用Autosar标准下的Profile01

               Counter Offset(Bit):56

               Checksum Offset(Bit):0

               Data ID Mode:DataID Both

               Data ID:0x01AB

               Max Delta Counter Init: 2

               Sync Counter Init: 1

               Max No New Or Repeatd Data: 14

       我们一个一个来解释这些都是些什么东西,有什么用。


        Counter Offset(Bit):56,Checksum Offset(Bit):0。

        对于这两个就很容易懂了,如下图,就是Checksum和Counter的位置在报文的什么地方


       Data ID Mode

       DataID的模式,共有四种模式可选:    

                E2E_P01_DATAID_BOTH
                E2E_P01_DATAID_ALT
                E2E_P01_DATAID_LOW
                E2E_P01_DATAID_NIBBLE

       那么,DataID是什么东西呢?

       以E2E_P01_DATAID_BOTH为栗子。

       首先,我们要知道,DATAID_BOTH,就是DataID为两个字节,且高字节叫做DataIDHigh,低字节为DataIDLow。

        根据我们目前这个需求,DataID为0x01AB(即DataIDHigh = 0x01,DataIDLow=0xAB),E2E校验的范围为Byte1-Byte7(Byte0用来存计算结果Checksum的值)。

        由于Byte1-Byte7共7个Byte,在校验的过程的中会把报文的Byte1-Byte7提取出来,放到一个新的数组里,新的数组长度为2+7=9(DataID长度+数据长度)。如数组的名字为Data[9]。则,Data[0] = DataIDLow(即0xAB),Data[1] = DataIDHigh(即0x01),Data[2]-Data[8]为报文的Byte1-Byte7。

        最后把整理好的Data数据进行算法计算。


        Max Delta Counter Init:

       关于这个参数,官方解释如下:

        简单来说就是说最大容忍Counter的间隔(,因为Counter是按1递增的,因此这参数即最大容忍丢失帧数)。正如它的例子说:如果MaxDeltaCounterInit配置为1,那么当在接收到上一帧的Counter为1的时候(下一帧若counter为2就不说了,因为Counter为2即没有丢帧),下一帧可以接收counter为3,但不能counter为4。因为1与3直接差了一帧(也就是丢失一帧了)。1与4直接已经差了2帧(也就是丢失两帧了),所以Counter为4不在容忍范围内了。

        转换成直观的例子:

        ①如连续接收到的报文Counter分别为:1、3、4、5、6、7。那么Counter值为3时,虽然中间缺失了一帧(Counter值为2的帧),但在容忍范围内。

        ②如连续接收到的报文Counter分别为:1、8、9、10、11、12。那么Counter值为8时,中间缺失了不止一帧,因此不在容忍范围内。


        Sync Counter Init:

        官方解释如下:

        

         关于这个参数,我们需要在后面讲E2E返回状态为E2E_P01STATUS_SYNC的时候才能反过来讲明白。


         对于E2E参数,官方图形解释如下:

使用Vector工具配置报文E2E的各个栗子如下:

        好了,其实讲到目前为止,你对这些参数应该还是明白的云里雾里。但要彻底明白这些参数是什么东西,有什么具体作用,需要知道接收到报文后进行E2E校验产出的东西------E2E状态


E2E状态:

        接收到含E2E报文后,对E2E报文的检查结果就会有对应的E2E状态供应用层读取,应用层根据E2E状态决定接收到的数据是否使用,并根据E2E状态记录相关的故障,如Checksum校验错误故障等。

typedef enum {E2E_P01STATUS_OK = 0x00,E2E_P01STATUS_NONEWDATA = 0x1,E2E_P01STATUS_WRONGCRC = 0x2,E2E_P01STATUS_SYNC = 0x03,E2E_P01STATUS_INITIAL = 0x4,E2E_P01STATUS_REPEATED = 0x8,E2E_P01STATUS_OKSOMELOST = 0x20,E2E_P01STATUS_WRONGSEQUENCE = 0x40
} E2E_P01CheckStatusType;

E2E_P01STATUS_WRONGCRC:

        接收到的E2E报文Checksum验证失败。比如E2E算法、或DataID的值、或E2E校验的范围配置得跟需求不符合,各个节点计算没统一起来,都会导致Checksum验证失败。

E2E_P01STATUS_SYNC:

        出现这个状态共有两种情况(假设MaxDeltaCounterInit配置为1,SyncCounterInit配置为2):

        ①初始化阶段。

        初始化,即上电后从没有接收到该报文。假设现在上电后接收到如下连续报文Counter分别为:2、3、4、5、6。那么Counter为3、Counter为4的时候,就是同步阶段。E2E状态为:E2E_P01STATUS_SYNC。

        ②出现Counter值状态为E2E_P01STATUS_WRONGSEQUENCE之后。

        即上一帧接收到Counter的值超过了MaxDeltaCounterInit。然后当前接收到Counter的值为正常。如接收到的连续报文的Counter值分别为:0、4、5、6、7、8。因此当Counter值为4时,E2E状态为E2E_P01STATUS_WRONGSEQUENCE。由于SyncCounterInit配置为2,E2E状态在Counter值为5、Counter值为6时,都为同步状态。E2E_P01STATUS_SYNC。

E2E_P01STATUS_INITIAL:

        初始化阶段。即上电后就没接收到E2E报文。E2E就会持续保持初始化状态。

E2E_P01STATUS_REPEATED:

         接收到的E2E报文Counter值重复。如接收到的连续报文的Counter值分别为:2、2、3、4、4、5。则,在接收到Counter值为第二个2时,E2E状态为E2E_P01STATUS_REPEATED。

E2E_P01STATUS_OKSOMELOST:

         接收到的E2E报文连续两帧之间的Counter差值大于1(Counter差值为1时,即Counter正常,如:0、1、2、3、4),但小于MaxDeltaCounterInit。(简单来说,就是前后连续两帧报文的Counter值不是连续的,但在容忍范围内)。如MaxDeltaCounterInit配置为1,接收到的连续报文的Counter值分别为:0、2、4、5、6、7。则,在接收到Counter值位2时,E2E状态为E2E_P01STATUS_OKSOMELOST。

E2E_P01STATUS_WRONGSEQUENCE :

         接收到的E2E报文连续两帧之间的Counter差值大于MaxDeltaCounterInit。如MaxDeltaCounterInit配置为1,接收到的连续报文的Counter值分别为:0、3、4、5、6、7。则,在接收到Counter值位3时,E2E状态为E2E_P01STATUS_WRONGSEQUENCE 。

E2E_P01STATUS_NONEWDATA:

        一个报文周期内未接收到该E2E报文。

E2E_P01STATUS_OK:

        接收到的E2E报文Checksum验证通过,且Counter验证正确。


另外还有下面的东西,应该不止。我下次再展开说(今晚太晚了,下次再修改):

DataIDNibbleOffset

        官方定义如下

        这个参数只有在DataID模式选择为“E2E_P01_DATAID_NIBBLE ”是会用到。目前我没用到,所以我也不知道这玩意干啥用的(看半天也没看懂-_-''')....


MaxNoNewOrRepeatedData

         

        当接收到重复数据次数小于该配置参数,则接收端不需要执行数据同步处理


         Autosar官方标准文档有如下所示报文接收检查流程图(太复杂了,大家随便看看就好了):


以下代码运行即可得到以Autosar官方标准的E2E_Profil01计算的结果(发送)。其中:

Checksum位置为Byte0

Counter位置为Byte7的低四位(即Bit56)

DataID模式为DATAID_BOTH且DataID=0x00AD。

注:以下是报文发送的例子。因为是发送,所以是没有E2E的状态处理的。

代码如下:

main.c

#include <stdio.h>
#include "typedef_datatype.h"
#include "E2E_Config.h"uint16 DataID = 0x00AD;//DataID_Low = 0xAD    DataID_High = 0x00    
uint8 Test_Data_Array[8] = { 0x00, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x73, 0x20 }; //Byte0-Byte7   Test Data
E2E_P01ConfigType E2E_Profile01_Test_Config = {56,						//CounterOffset0,						//CRCOffset177,					//DataID0,					//DataIDNibbleOffsetE2E_P01_DATAID_BOTH,	//DataIDMode64,						//DataLength0,					//MaxDeltaCounterInit0,					//MaxNoNewOrRepeatedData0					//SyncCounterInit
};void main(void)
{for (uint8 counter = 0; counter < 15; counter++){Test_Data_Array[7] = (Test_Data_Array[7] & 0xF0) | counter;Test_Data_Array[0] = E2E_P01ComputeCRC(Test_Data_Array, &E2E_Profile01_Test_Config, 0xFF);for (uint8 i = 0; i < 8; i++){printf("%x ", Test_Data_Array[i]);}printf("\n");}}

E2E_Config.h

#ifndef E2E_Config_H_
#define E2E_Config_H_#include <stdio.h>
#include "typedef_datatype.h"/* For CRC 8*/
#define CRC8_START_VALUE        0xFFU
#define CRC8_XOR                0xFFU
/* CRC 8 Configuration* Possible values and the mode decides what method to be used*/
#define CRC_8_HARDWARE (0x01) /* Not supported */
#define CRC_8_RUNTIME  (0x02)
#define CRC_8_TABLE    (0x04) /* Default value */#define CRC_8_MODE      CRC_8_RUNTIME/* E2E Profile01 */
#define CRC8_POLYNOMIAL			0x1DUtypedef enum {E2E_P01_DATAID_BOTH = 0x0,E2E_P01_DATAID_ALT = 0x1,E2E_P01_DATAID_LOW = 0x2,E2E_P01_DATAID_NIBBLE = 0x3
} E2E_P01DataIDMode;typedef struct {uint16 CounterOffset;uint16 CRCOffset;uint16 DataID;uint16 DataIDNibbleOffset;E2E_P01DataIDMode DataIDMode;uint16 DataLength;uint8 MaxDeltaCounterInit;uint8 MaxNoNewOrRepeatedData;uint8 SyncCounterInit;
} E2E_P01ConfigType;uint8 Crc_CalculateCRC8(const uint8* Crc_DataPtr, uint32 Crc_Length, uint8 Crc_StartValue8, boolean Crc_IsFirstCall);
uint8 E2E_P01ComputeCRC(const uint8* Crc_DataPtr, const E2E_P01ConfigType* ConfigPtr, uint8 Counter);#endif

E2E.c

#include "E2E_Config.h"static uint8 CalculateCRC8(const uint8* message, uint32 nBytes, uint8 start, uint8 poly)
{uint8  remainder = start;uint8  bit;uint8  topbit = 0x80;/* Perform modulo-2 division, a byte at a time. */for (uint32 byte = 0; byte < nBytes; byte++) {/* Bring the next byte into the remainder. */remainder ^= *message;message++;/* Perform modulo-2 division, a bit at a time. */for (bit = 8; bit > 0; bit--) {/* Try to divide the current data bit. */if ((remainder & topbit) != 0u) {remainder = (uint8)(remainder << 1) ^ poly;}else {remainder = (remainder << 1u); /*lint !e734 Lint exception: Intentional */}}}return remainder;
}uint8 Crc_CalculateCRC8(const uint8* Crc_DataPtr, uint32 Crc_Length, uint8 Crc_StartValue8, boolean Crc_IsFirstCall)
{uint8 crc = 0;    /* Default return value if NULL pointer */if (Crc_DataPtr != NULL){crc = (TRUE == Crc_IsFirstCall) ? CRC8_START_VALUE : (Crc_StartValue8 ^ CRC8_XOR);#if CRC_8_MODE == CRC_8_RUNTIMEcrc = CalculateCRC8(Crc_DataPtr, Crc_Length, crc, CRC8_POLYNOMIAL);
#elif CRC_8_MODE == CRC_8_TABLEfor (uint32 byte = 0; byte < Crc_Length; byte++){crc = crc8_tab[crc ^ *Crc_DataPtr];Crc_DataPtr++;}
#endif/* Only XOR value if any calculation was done */crc = crc ^ CRC8_XOR;}return crc;}uint8 E2E_P01ComputeCRC(const uint8* DataPtr, const E2E_P01ConfigType* ConfigPtr, uint8 Counter)
{uint8 crc;uint8 CrcLength;uint8 LocalDataID[2];uint16 CalculatedOffset;uint16 CalculatedLength;switch (ConfigPtr->DataIDMode){case E2E_P01_DATAID_BOTH:{LocalDataID[0] = (uint8)(ConfigPtr->DataID);LocalDataID[1] = (uint8)(ConfigPtr->DataID >> 8u);CrcLength = 2;break;}case E2E_P01_DATAID_LOW:{LocalDataID[0] = (uint8)ConfigPtr->DataID;CrcLength = 1;break;}case E2E_P01_DATAID_NIBBLE:{LocalDataID[0] = (uint8)ConfigPtr->DataID;LocalDataID[1] = 0;CrcLength = 2;break;}case E2E_P01_DATAID_ALT:{CrcLength = 1;if ((Counter & 0x01u) == 0u){LocalDataID[0] = (uint8)ConfigPtr->DataID;}else{LocalDataID[0] = (uint8)(ConfigPtr->DataID >> 8u);}break;}default:LocalDataID[0] = 0u;CrcLength = 0u;break;}crc = Crc_CalculateCRC8(LocalDataID, CrcLength, 0xFF, FALSE);CalculatedOffset = ConfigPtr->CRCOffset >> 3u;if ((CalculatedOffset) > 0u){crc = Crc_CalculateCRC8(DataPtr, CalculatedOffset, crc, FALSE);}CalculatedLength = ConfigPtr->DataLength >> 3u;if (CalculatedOffset < (CalculatedLength - 1u)){crc = Crc_CalculateCRC8(&DataPtr[CalculatedOffset + 1u], (uint32)CalculatedLength - CalculatedOffset - 1u, crc, FALSE);}return crc ^ 0xFFu;}

参考:AUTOSAR E2E 简介_Archieeeeee的博客-CSDN博客_autosar e2e


http://chatgpt.dhexx.cn/article/SIhmeuc9.shtml

相关文章

功能安全专题之端到端(E2E) 的通信保护

本文来自AUTOSAR技术资料。 前言 功能安全&#xff08;Functional Safety&#xff09;是一项系统特性&#xff0c;由于基于功能安全的设计会影响到系统设计&#xff0c;所以从系统开发初始阶段就要进行考虑。由于软件的复杂度会影响 到功能安全的设计&#xff0c;所以在AUTOS…

AUTOSAR的E2E通信安全

导语&#xff1a;近期项目中遇到一些E2E的诊断故障&#xff0c;涉及到整车需求和AutoSAR配置&#xff0c;对这个概念重新做了下梳理&#xff0c;与大家交流。由于E2E机制比较成熟&#xff0c;本文章内容更多出自于AutoSAR标准、ISO 26262 和相关文献&#xff0c;这里只捡重点和…

E2E通信保护协议学习笔记

E2E通信保护协议学习笔记 最近在做功能安全方面工作&#xff0c;想了解E2E保护的问题。本文试着说明两个点&#xff1a; 功能安全需要考虑通信失效造成的影响&#xff0c;因此E2E通信保护协议被提出&#xff0c;以满足功能安全要求&#xff1b; 简单介绍E2E通信保护协议机制。…

什么是 E2E 保护 ?

安全在每个领域都是一个永恒的话题&#xff0c;汽车也不例外&#xff0c;而随着最近几年汽车电动化、智能化和网联化的发展&#xff0c;汽车安全也越来越受到用户及开发人员的重视&#xff0c;安全的要素也是多方面的&#xff0c;例如用户可能关心在使用车机系统时的隐私安全、…

HVS颜色空间的提取

在日常的图片处理中&#xff0c;常常要把RGB转成HVS&#xff0c;然后再提取色调、亮度、饱合度通道图片进行操作&#xff0c;网上大多介绍都只是提到转换&#xff0c;如果提取都不准确&#xff0c;我这里记录一下准确提取的方法。V&#xff0c;S提取只要将值乘255就可以&#x…

matlab绘制hsv色轮图

% 生成网格 tListlinspace(0,2.*pi,300); rListlinspace(0,1,100); [theta,R]meshgrid(tList,rList);% 角度及半径转换为坐标 Xcos(thetapi).*R; Ysin(theta).*R; Zzeros(size(X));% 构造hsv网格并转换为rgb网格 hsvMeshcat(3,theta./2./pi,ones(size(R)),R); rgbMeshhsv2rgb(h…

图像融合:Exposure Fusion Using Boosting Laplacian Pyramid

Exposure Fusion Using Boosting Laplacian Pyramid 文章目录 Exposure Fusion Using Boosting Laplacian PyramidJND ModelLuminance AdaptationContrast MaskingOverall JND Model A Hybrid Exposure Weight MeasurementLocal Exposure WeightGlobal Exposure WeightJND-Base…

基于主动视觉机制的深度学习--一个综合池化框架

卷积神经网络(CNN)是深度学习的代表算法之一&#xff0c;长期以来被广泛应用于图像识别领域。它是受到了生物处理过程的启发&#xff0c;通过模仿人类视觉系统(HVS)的工作机制&#xff0c;完成各种视觉任务等。但与HVS相比&#xff0c;CNN不能够像人类一样&#xff0c;迅速的分…

第13章:直方图处理

第13章&#xff1a;直方图处理 一、直方图的含义&#xff1a;1. 普通直方图&#xff1a;2. 归一化直方图&#xff1a; 二、绘制直方图&#xff1a;1. 使用Numpy绘制直方图&#xff1a;2. 使用OpenCV绘制直方图&#xff1a;3. 使用掩码绘制直方图&#xff1a; 三、直方图均衡化&…

通过matlab,基于DCT变换,利用hvs实现水印嵌入强度自适应

我真的会谢&#xff0c;为什么我跑出来是一片黑呀&#xff1f;本matlab小白跪求matlab大佬答疑解惑555555感谢 以下是我的程序&#xff1a; % 读取原始图像和水印图像 I imread(lena.bmp); W imread(waterMark.bmp);% 将图像转为灰度图&#xff0c;并将水印调整为与原始图像…

基于HVS 的结构相似性的视频质量评价

清华大学的汪志兵&#xff0c; 廖煜鹏&#xff0c; 汪 博&#xff0c; 秦明海&#xff0c; 林行刚等人在《通信技术》2010年第2期上发表。   HVS 对不同频率分量的敏感性不同&#xff0c;对视频帧不同部分的关注度也不相同。 为了达到更好的效果&#xff0c;论文中引入3 个因…

一种基于HVS特性的视频质量评测方法

本篇论文是由厦门大学的袁飞&#xff0c;黄联芬&#xff0c;姚彦发表于《光电工程》2008年1月刊上。   本文针对视频质量的评测应用&#xff0c;通过在视频帧内图像和帧间图像的处理过程中引入人眼视觉系统(HVS)的主要特性&#xff0c;克服传统PSNR 算法在序列质量检测应用方…

数字水印算法matlab源程序 matlab版数字水印算法 /DCT/DWT/LSB/HVS/W-SVD数字水印源码 数字水印的嵌入和提取 W-SVD数字水印实现

发以下多套系统源码&#xff1a; 1、matlab版数字水印算法 2、MATLAB数字水印 源代码文档 3、数字水印技术matlab代码 4、数字水印 JPEG压缩 matlab代码 5、数字水印 添加噪声 matlab代码 6、各种数字水印的matlab源代码&#xff08;有DFT&#xff0c;DCT&#xff0c;小波变换等…

基于hvs图像水印matlab和psnr nc的计算 首先读取图像和水印,进行图像加印

基于hvs图像水印matlab和psnr nc的计算 首先读取图像和水印&#xff0c;进行图像加印 然后进行攻击 攻击方式有白噪声&#xff0c;裁剪&#xff0c;旋转10度&#xff0c;压缩&#xff0c;和无攻击&#xff0c;然后最后还原水印。 ID:31314617581701451好好学习

opencv RGB2HVS

RGB色彩空间和HSV色彩空间的理解 本文的结构如下&#xff1a; 1、RGB色彩空间 2、HSV色彩空间&#xff08;附HSV颜色分量范围表&#xff09; 3、RGB到HSV的转换的Demo   使用OpenCV实现RGB转HSV&#xff0c;并通过滑动条动态设定HSV阈值   自己写程序&#xff0c;实现…

HVS颜色模型(六角锥体模型)

色调&#xff08;H&#xff09;&#xff1a;用角度度量&#xff0c;取值范围为0~360&#xff0c;从红色开始按逆时针方向计算&#xff0c;红色为0&#xff0c;绿色为120&#xff0c;蓝色为240、他们的补色是&#xff1a;黄色为60&#xff0c;青色为180&#xff0c;紫色为300&am…

ISP——HVS

本片博文是一篇笔记&#xff0c;是在看论文的时候碰到下面一段话&#xff0c;反复把论文看了三遍才弄懂&#xff0c;刚开始老觉得和gamma的特性是反的&#xff0c;还一度怀疑论文些错了&#xff0c;经过反复琢磨才弄明白&#xff0c;故此写下笔记记录 Higher gap in intensity…

HVS的真相

HVS的真相 人眼视觉系统&#xff08; human visual system&#xff0c;HVS&#xff09;是人类通过感知光线形成视觉的系统&#xff0c;是人类捕获外界信息最关键的系统之一。HVS在视频编码的主观优化中发挥重要作用。关于HVS有以下特性不得不知&#xff1a; HVS对高频信号的失…

人类视觉系统(Human Visual System,HVS)

人类通过人类视觉系统&#xff08;HVS&#xff09;来获取外界图像信息&#xff0c;当光辐射刺激人眼时&#xff0c;将会引起复杂的生理和心理变化&#xff0c;这种感觉就是视觉。 人类视觉系统&#xff08;HVS&#xff09;作为一种图像处理系统&#xff0c;它对图像的认知是非均…