3. CAPL事件驱动

CAPL事件驱动:on message接收与解析 学习卡片

任务说明

本案例要求使用CANoe CAPL脚本接收指定CAN报文,并从中解析出目标信号的物理值。以动力系统中常见的发动机转速报文(ID 0x1F4)为例,该报文包含8个数据字节,其中转速信号(EngineSpeed)位于字节2和字节3(共16位,Intel格式,因子0.25 rpm/bit,偏移量0)。完成目标:在CANoe仿真环境中,当总线上出现该报文时,CAPL程序能够正确提取转速原始值并转换为带单位的物理值,通过Write窗口输出。

实现方案

在CANoe中新建CAPL测试节点,通过on message事件处理器捕获目标报文。使用this.byte()函数按字节索引读取数据,按Intel格式组合16位原始值,再应用线性转换公式物理值 = 原始值 × 因子 + 偏移量得到最终转速。程序结构包含报文定义、信号解析函数和输出逻辑三部分。

CAPL代码实现

/* 接收CAN消息并解析信号值 - 发动机转速示例 */
/* 适用于CANoe 10.x及以上版本 */

variables
{
  message 0x1F4 g_EngineSpeedMsg;      // 目标报文:发动机转速
  const int    g_StartBit = 16;        // 信号起始位(bit 16 = 字节2的bit0)
  const int    g_SignalLength = 16;    // 信号长度16位
  const double g_Factor = 0.25;        // 因子:0.25 rpm/bit
  const double g_Offset = 0.0;         // 偏移量:0 rpm
  double g_EngineSpeedPhys;            // 解析后的物理值
}

/* 信号解析函数:从报文数据中提取指定起始位、长度的Intel格式信号 */
double SignalExtract(message *msg, int startBit, int signalLength, double factor, double offset)
{
  int rawValue = 0;
  int byteIndex;
  int bitInByte;
  int i;

  // Intel格式(小端):信号从起始位开始,逐位向高字节方向排列
  for (i = 0; i < signalLength; i++)
  {
    byteIndex = (startBit + i) / 8;
    bitInByte = (startBit + i) % 8;
    if ((msg.byte(byteIndex) & (1 << bitInByte)) != 0)
    {
      rawValue |= (1 << i);
    }
  }

  // 线性转换:物理值 = 原始值 × 因子 + 偏移量
  return (rawValue * factor + offset);
}

/* 报文接收事件处理 */
on message 0x1F4
{
  // 调用解析函数获取转速物理值
  g_EngineSpeedPhys = SignalExtract(this, g_StartBit, g_SignalLength, g_Factor, g_Offset);

  // 输出解析结果
  write("收到报文 ID=0x%X, 原始数据: %02X %02X %02X %02X %02X %02X %02X %02X",
        this.id,
        this.byte(0), this.byte(1), this.byte(2), this.byte(3),
        this.byte(4), this.byte(5), this.byte(6), this.byte(7));
  write("发动机转速 = %.1f rpm", g_EngineSpeedPhys);
}

代码说明

上述代码的核心逻辑如下:

  • 报文定义:通过message 0x1F4声明需要接收的CAN报文ID。
  • 信号参数:起始位16对应字节2的bit0,长度16位,因子0.25,偏移量0。
  • 解析函数:SignalExtract逐位检查报文数据,按Intel格式组装原始值,再完成线性换算。该函数可复用,只需修改起始位、长度和因子即可解析同一报文中的其他信号。
  • 事件处理:on message 0x1F4在每次收到该ID报文时自动触发,调用解析函数并输出结果。

验证方法

在CANoe中按以下步骤验证:

  1. 新建工程并添加CAN通道,在Simulation Setup中插入一个CAPL测试节点,将上述代码粘贴到节点的CAPL编辑器中。
  2. 在IG(Interaction Generator)或CAN IG模块中,配置发送ID为0x1F4的周期性报文,并设置数据字节。例如设置字节2=0x00、字节3=0x64,则原始值=0x6400=25600,物理值=25600×0.25=6400.0 rpm。
  3. 启动测量(按F5或点击Start),观察Write窗口输出。

判定标准:当IG发送字节2=0x00、字节3=0x64的报文时,Write窗口显示“发动机转速 = 6400.0 rpm”,且原始数据打印为“00 64 00 00 00 00 00 00”,即表示解析正确。可修改字节2和字节3的值(如0x10、0x27对应原始值0x2710=10000,物理值2500.0 rpm)再次验证,输出应随输入线性变化。

CAN报文信号解析验证拓扑 CAN 总线 (500 kbps) IG 报文发生器 发送 ID=0x1F4 CAPL 测试节点 on message 0x1F4 报文帧 信号解析流程 1. 读取 byte(2), byte(3) 2. Intel格式组合16位原始值 3. 物理值 = 原始值 × 0.25 Write 窗口输出 发动机转速 = 6400.0 rpm 报文数据布局: Byte0 Byte1 Byte2 (LSB) Byte3 (MSB) Byte4-7

关键点提示

  • Intel格式(小端)中,信号低位字节在前,因此字节2是低8位,字节3是高8位,组合公式为raw = byte(2) | (byte(3) << 8)。
  • 若信号为Motorola格式(大端),位排列顺序相反,需调整提取逻辑,但本案例仅针对Intel格式。
  • 因子0.25表示原始值每增加1,物理转速增加0.25 rpm,因此16位原始值最大65535对应16383.75 rpm,满足发动机转速范围。