You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CAPL实现CRC8 SAE-J1850校验的CAN报文发送脚本求助

CAPL实现带CRC8 SAE-J1850校验、报文计数器的32位CAN报文发送脚本

以下脚本适配CANoe/CANalyzer环境,可直接加载到CAPL节点运行,完全匹配你给出的CRC参数:多项式x^8+x^4+x^3+x^2+1(对应十六进制值0x1D)、初始值0xFF,支持32位业务数据打包、计数器滚动、CRC自动计算,输出符合CAN总线发送规范。

报文数据场默认布局(DLC=6)

校验范围覆盖业务数据+计数器,共5字节,校验值存在最后1字节

  • Byte0~Byte3:32位有效业务数据
  • Byte4:滚动报文计数器
  • Byte5:CRC8 SAE-J1850校验值

完整CAPL代码

variables
{
  // 按需修改目标ECU的CAN报文ID
  const long c_TxMsgId = 0x123;
  // 按需修改周期发送间隔,单位ms
  const int c_TxPeriod = 100;
  // 报文滚动计数器全局变量
  byte g_msgCounter = 0;
  // 32位业务数据缓存,可在任意事件逻辑中更新该值
  dword g_payloadData = 0x00;
  // CAN发送报文对象
  message c_TxMsgId g_TxMsg;
  // 周期发送定时器
  msTimer t_txTimer;
}

/**
 * @brief CRC8 SAE-J1850计算函数
 * @param data 待校验数据数组
 * @param len 待校验数据长度
 * @return 计算得到的8位CRC结果
 */
byte CalcCRC8_SAEJ1850(byte data[], int len)
{
  byte crc = 0xFF; // 匹配指定初始值
  const byte poly = 0x1D; // 匹配指定多项式
  int i, j;

  for(i = 0; i < len; i++)
  {
    crc ^= data[i];
    for(j = 0; j < 8; j++)
    {
      crc = (crc & 0x80) ? ((crc << 1) ^ poly) : (crc << 1);
    }
  }
  // 标准SAE-J1850要求最终结果异或0xFF,若ECU校验失败可注释该行测试
  crc ^= 0xFF;
  return crc;
}

/**
 * @brief 定时器触发的报文打包发送逻辑
 */
on timer t_txTimer
{
  byte txBuf[6];
  byte crcResult;

  // 填充32位有效载荷,默认小端序,大端序可调整字节赋值顺序
  txBuf[0] = (byte)(g_payloadData & 0xFF);
  txBuf[1] = (byte)((g_payloadData >> 8) & 0xFF);
  txBuf[2] = (byte)((g_payloadData >> 16) & 0xFF);
  txBuf[3] = (byte)((g_payloadData >> 24) & 0xFF);

  // 填充计数器,自增后byte类型溢出自动回0
  txBuf[4] = g_msgCounter;
  g_msgCounter++;

  // 计算前5字节的CRC值并填充
  crcResult = CalcCRC8_SAEJ1850(txBuf, 5);
  txBuf[5] = crcResult;

  // 配置报文DLC、装载数据并发送
  g_TxMsg.dlc = 6;
  for(int idx = 0; idx < 6; idx++)
  {
    g_TxMsg.byte(idx) = txBuf[idx];
  }
  output(g_TxMsg);

  // 重启定时器维持周期发送
  setTimer(t_txTimer, c_TxPeriod);
}

/**
 * @brief 节点启动初始化
 */
on start
{
  g_msgCounter = 0;
  // 可自定义32位载荷初始值
  g_payloadData = 0x12345678;
  // 启动首次发送定时
  setTimer(t_txTimer, c_TxPeriod);
}

使用调整说明

  • 若协议要求计数器仅在0~15范围滚动,可在g_msgCounter++;后新增一行g_msgCounter &= 0x0F;即可。
  • 若ECU采用大端序解析32位数据,只需要把txBuf[0]~txBuf[3]的赋值顺序倒序排列即可。
  • 不需要周期发送时,可以把报文打包发送的逻辑抽成独立自定义函数,在按键触发、信号变化触发、诊断响应触发等对应事件中调用即可。
  • 若使用CAN FD报文,只需要在报文对象定义时增加CAN FD属性、调整DLC为对应CAN FD长度值,CRC计算逻辑不需要修改。
  • CRC校验不通过时优先检查两个点:一是最终异或值是否和ECU端一致,可尝试注释crc ^= 0xFF;测试;二是校验范围是否覆盖了正确的字节,部分协议会把CRC本身也纳入校验范围,可调整CalcCRC8_SAEJ1850的长度参数测试。

内容的提问来源于stack exchange,提问作者TechGeek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 09:18:19