仿真CAN报文发送的CRC校验算法(附CAPL代码)

文章目录


前言

关于CRC校验的基本理论、算法实现网上已经有很多介绍文章,本文不再赘述。只是记录在项目测试中真正开发CRC算法并进行测试的一些体会。

一、为什么CAN报文有CRC?

首先从CAN帧结构层面上看,在报文Data后紧跟着的是CRC场,通信收发双方通过约定的算法进行CRC计算来实现数据传输检错功能,以此降低误码率,保证数据传输的正确性和完整性。从应用层面来看车辆的车速档位、Usermode、Carmode等信息需要保证正确传输以达到数据安全。这也是为什么不是所有帧都需要做CRC校验。

二、怎么确定是否需要做CRC校验?

如下图,在DBC或者ARXML中当需要仿真发送的报文中包括checksum和Rollingcounter信号时,就需要进行CRC校验算法开发。这里有几个点需要注意:

  • 仿真发送的报文才需要,接收报文不需要;
  • checksum和Rollingcounter信号名不一定是唯一的,要注意识别。有的可能写CRC、RC等其他形式。当仿真发送报文没有任何作用时,就可以去看看是不是有CRC信号需要算法校验。
  • CRC算法也是多样的,注意根据规范开发。核心数据包括:多项式、初始CRC值、最终异或值。重点是理解CRC算法逻辑,这样不论是在CANoe、TSMaster、Veristand中都可以进行开发。

三、CAPL代码实现CRC算法

上面提到,重点是理解CRC算法逻辑然后去有针对性的开发。下面以LIN的CRC为例,使用CAPL进行CRC demo代码的实现。可以根据实际开发需要进行调整。

c 复制代码
/*@!Encoding:936*/
includes
{
  
}

variables
{
  byte i;
  linFrame *msg;
  int flag;
  byte index;
  byte crc_item;
  byte CRC_CheckSum;
  byte crcValue = 0x00;
  byte xorValue = 0x00;
  byte Frame_Data[7];
}

void SimulationCRC(long MsgID,int CycleTime)
{
  msg.id = 0x00;
  msg.msgChannel = 1;
  msg.dlc=8;
  msg.rtr = 0;  //RTR在output发送帧时使用,为0将重新配置响应数据;为1向总线发送帧头,配合主模式使用
  
  msg.byte(1) = i + 0x80;
  flag = 1;
  i++;
  if(i == 0xF)
  {
    i = 0x0;
  }
  //直接定义byte字节值;或者去定义报文信号
  msg.byte(2) = 0x02;
  msg.byte(3) = 0x03;
  msg.byte(4) = 0x04;
  msg.byte(5) = 0x05;
  msg.byte(6) = 0xC6;
  msg.byte(7) = 0x07;
  Frame_Data[0] = msg.byte(1);
  Frame_Data[1] = msg.byte(2);
  Frame_Data[2] = msg.byte(3);
  Frame_Data[3] = msg.byte(4);
  Frame_Data[4] = msg.byte(5);
  Frame_Data[5] = msg.byte(6);
  Frame_Data[6] = msg.byte(7);
  if(flag == 1)
  {
    CRC_CheckSum = crc8Sumu(Frame_Data,7);
    flag = 0;
  } 
  msg.byte(0) = CRC_CheckSum;
  output(msg);
  flag=1;
}

on linFrame *
{
  if(this.id == 0x00)
  {
     SimulationCRC(0x00, 50);
  }
}

// ----------------------<crc8Sumu>-------------------------
byte crc8Sumu(byte data[], int Datalen)
{
  byte CRCInitValue = 0x01;
  byte CRCPolynomial = 0x02;
  byte CRCXORValue = 0x03;

  int i, j;
  byte Rtn;
  Rtn = CRCInitValue;
  for (i = 0; i < Datalen; i++)
  {
    Rtn ^= data[i];   //异或赋值
    for (j = 0; j < 8; j++)
    {
      if (Rtn & 0x80)
      {
        Rtn = (Rtn << 1) ^ CRCPolynomial; //左移一位后 异或运算
      }
      else
      {
        Rtn <<= 1;
      }
    }
  }
  Rtn ^= CRCXORValue;
  return Rtn;
}
相关推荐
学习星球19 小时前
OFDM技术精讲:正交性推导、循环前缀原理与80行Python链路仿真(附实测数据)
算法·面试·前端框架
alphaTao1 天前
LeetCode 每日一题 2026/8/24-2026/8/30
python·算法·leetcode
草莓熊Lotso1 天前
【Redis 初阶】Set 类型深度解析:去重集合的运算能力与实战场景
linux·网络·数据库·windows·redis·tcp/ip·缓存
XR1234567881 天前
汽车制造园区网络怎么建?柔性产线与 AGV 的选型逻辑
网络·汽车·制造
Interview Aid1121 天前
TikTok OA 四题分享|半小时内 AC,题目基本都是实现题
java·开发语言·算法·面试·职场和发展
顶点多余1 天前
那些在算法中适合巩固的知识点---1
java·前端·算法
IT大白鼠1 天前
MSF二次开发与自定义模块编写
网络·安全·web安全·msf
Julien20041 天前
调查和解决 SELinux 问题
linux·运维·服务器·网络·学习方法
AI情绪识别开源1 天前
检信 ALLEMOTION OS 加密打包可执行程序 — 全面测试报告版本: v1.3功能测试 / 性能测试 /
开发语言·数据结构·人工智能·功能测试
罗西的思考1 天前
【Agentic RL / 强化学习框架】Molt 设计解读
人工智能·算法·机器学习