3. 基于Vector工具链的LIN信号故障注入

任务目标

本案例使用Vector工具链(CANoe + LINoe)向LIN总线注入信号级故障,验证从节点在收到异常信号值时的响应行为。核心目标是:通过CAPL脚本在总线报文发送前篡改信号值,模拟真实世界中的信号错误,并观察从节点是否按设计进行故障处理。

环境与依赖

  • Vector CANoe(建议11.0及以上版本),需包含LINoe选项
  • Vector LIN接口硬件(如VN1630/VN1640)
  • 被测LIN从节点(含至少一个可观测响应信号)
  • LIN主节点调度表已配置,总线通信正常

实现方案

采用CAPL的on LINFrame事件处理器,在从节点接收帧之前拦截并修改信号值。通过系统变量控制注入开关与注入值,实现运行时动态切换正常/故障信号,无需重新编译。

关键完整代码

/* LIN_Signal_Injection.cap */

/* 系统变量定义(在CANoe中创建) */
/* sysvar: SysVar_Inject_Enable (int, 0/1) */
/* sysvar: SysVar_Inject_SignalValue (int, 0-255) */

variables
{
  /* 目标LIN帧ID(示例:0x18 = 主节点发送的传感器帧) */
  const long TARGET_FRAME_ID = 0x18;
  
  /* 目标信号在帧内的起始位与长度(示例:Byte0的低4位) */
  const long SIGNAL_START_BIT = 0;
  const long SIGNAL_LENGTH = 4;
  
  /* 原始信号值缓存 */
  int g_originalValue = 0;
}

/* 主节点发送帧前触发(在从节点接收前拦截) */
on LINFrame * // 使用通配符,在内部过滤目标ID
{
  LINFrame targetFrame;
  
  /* 仅处理目标帧 */
  if (this.ID != TARGET_FRAME_ID)
    return;
  
  /* 保存原始帧数据 */
  targetFrame = this;
  
  /* 读取原始信号值 */
  g_originalValue = (targetFrame.byte(0) >> SIGNAL_START_BIT) & 0x0F;
  
  /* 判断是否启用注入 */
  if (sysvar::SysVar_Inject_Enable == 1)
  {
    /* 构造故障信号:将目标信号位段替换为注入值 */
    int modifiedByte = targetFrame.byte(0);
    
    /* 清除原信号位段 */
    modifiedByte &= ~(0x0F << SIGNAL_START_BIT);
    
    /* 写入注入值(取低4位) */
    modifiedByte |= ((sysvar::SysVar_Inject_SignalValue & 0x0F) << SIGNAL_START_BIT);
    
    /* 更新帧数据 */
    targetFrame.byte(0) = modifiedByte;
    
    /* 输出调试信息 */
    write("LIN注入: 帧ID=0x%X, 原始值=%d, 注入值=%d", 
          this.ID, g_originalValue, sysvar::SysVar_Inject_SignalValue);
  }
  
  /* 将(可能被修改的)帧发送到LIN总线 */
  output(targetFrame);
  
  /* 禁止原帧继续发送 */
  _disableOriginalFrame();
}

/* 辅助函数:阻止原始帧自动发送 */
void _disableOriginalFrame(void)
{
  /* 通过设置标志位实现,具体取决于CANoe配置 */
  /* 若使用"LIN Frame"节点属性,可在此调用取消发送API */
  /* 本示例假设已配置为手动发送模式 */
}

/* 定时器:周期性记录从节点响应(用于验证) */
msTimer verifyTimer;
const long VERIFY_INTERVAL_MS = 1000;

on start
{
  setTimer(verifyTimer, VERIFY_INTERVAL_MS);
}

on timer verifyTimer
{
  /* 读取从节点反馈信号(示例:从节点状态帧ID=0x20) */
  LINFrame responseFrame;
  
  if (responseFrame.GetFrame(0x20) == 0) /* 0表示成功读取 */
  {
    int statusSignal = (responseFrame.byte(0) >> 2) & 0x03;
    write("验证: 从节点状态=0x%X (0=正常, 1=故障模式, 2=恢复)", statusSignal);
  }
  
  setTimer(verifyTimer, VERIFY_INTERVAL_MS);
}

运行与操作步骤

  1. 在CANoe中创建新工程,配置LIN通道并加载LDF文件
  2. 将上述CAPL代码添加到Measurement Setup中的CAPL节点
  3. 创建两个系统变量:SysVar_Inject_Enable(整数,默认0)和SysVar_Inject_SignalValue(整数,默认0)
  4. 编译CAPL代码,确保无错误
  5. 启动测量,确认LIN总线通信正常(观察Trace窗口)
  6. 在Watch窗口中将SysVar_Inject_Enable设为1
  7. 修改SysVar_Inject_SignalValue为期望的故障值(如0x5)
  8. 观察Write窗口中的注入日志与从节点状态变化

验证方法与判定标准

  • 注入生效验证:Write窗口应输出“LIN注入: 帧ID=0x18, 原始值=X, 注入值=5”,且Trace窗口中该帧的对应信号值显示为5
  • 从节点响应验证:当注入值超出从节点正常范围时,从节点状态信号应从“正常(0)”切换为“故障模式(1)”;将注入值恢复为正常范围后,从节点应回到“正常(0)”状态
  • 关闭注入验证:将SysVar_Inject_Enable设为0后,总线上的信号值恢复为原始值,从节点不再进入故障模式

常见问题

  • 帧未拦截:确认CAPL节点连接在LIN总线的正确位置(应位于主节点与从节点之间),且on LINFrame事件未被其他节点消费
  • 信号位段错误:核对LDF中信号定义与代码中的SIGNAL_START_BIT和SIGNAL_LENGTH是否一致
  • 从节点无响应:检查注入值是否超出从节点定义的信号范围,部分从节点对非法值直接丢弃帧而非进入故障模式