3. CAN/LIN 总线故障注入:总线 off、位错误、CRC 错误、信号超时

总线,是线控转向系统的神经网络。信号丢了、乱了、迟了,转向指令就传不过去。这一章我们专门聊 CAN/LIN 总线的故障注入。说白了,就是模拟总线“生病”的各种状态,看看系统扛不扛得住。

核心观点:总线故障注入不是乱搞破坏,而是验证通信协议栈的鲁棒性。你注入的每一个错误,都应该对应到 ISO 26262 中定义的通信故障模型。

3.1 总线 off 故障注入

总线 off,是 CAN 控制器最严重的自我保护状态。当发送错误计数器(TEC)超过 255,节点会自动离线。我见过不少工程师只测了“拔线”这种粗暴方式,其实真正的总线 off 注入要精细得多。

注入方法

  • 方法一:连续发送错误帧——通过工具(如 CANoe、PCAN-Explorer)持续发送违反 CAN 协议格式的报文,迫使目标节点 TEC 飙升。
  • 方法二:物理层干扰——在 CAN_H/CAN_L 之间接入可编程电阻,模拟短路或断路,触发总线 off。
  • 方法三:寄存器级注入——直接修改节点 CAN 控制器的 TEC 寄存器,强制进入 bus off 状态(需要调试接口)。
我的习惯:优先用方法一。因为它最接近真实场景,而且能精确控制错误注入的频次和时机。我曾经在项目里用 CANoe 的 IG(Interaction Layer)模块,每秒注入 200 个错误帧,3 秒内就让目标节点离线了。

测试观察点

观察项 预期行为 常见问题
节点恢复时间 总线 off 后,节点应在 128 个空闲位后自动恢复 恢复时间过长或无法恢复
应用层响应 转向系统应进入降级模式(如切换到冗余总线) 系统直接死机或输出错误扭矩
故障诊断记录 DTC 应正确记录总线 off 事件 诊断未触发或记录错误
注意:总线 off 恢复后,节点会重新参与总线仲裁。如果此时发送缓冲区还有积压报文,可能引发“恢复风暴”——多个节点同时发送,导致总线再次拥堵。我曾经在测试中遇到过,恢复后 500ms 内又触发了第二次总线 off。

3.2 位错误注入

位错误,是 CAN 总线最底层的错误。发送节点在发送位时,会回读总线电平。如果回读值与发送值不一致,就产生位错误。你想想看,如果总线被强拉成显性,而你要发送隐性位,那肯定报错。

注入技巧

  • 单比特翻转:在报文发送过程中,用工具强制翻转某个位(如将 ACK 槽的显性位改为隐性位)。
  • 多比特干扰:在 CRC 场或数据场连续注入多个错误位,模拟强电磁干扰。
  • 位时序偏移:通过调整采样点位置,让节点在错误的时间点采样,产生位错误。
// 示例:使用 CANoe CAPL 脚本注入单比特错误
on start {
  // 配置 CAN 通道,在报文 ID 0x123 的第 15 位注入错误
  canSetErrorFrameInjection(1, 0x123, 15, 1);
  write("位错误注入已启动 - 目标报文 0x123,位位置 15");
}
避坑指南:我曾经在测试中只关注数据场的位错误,忽略了 CRC 场的位错误。结果发现,CRC 场的位错误会导致节点重发,但应用层完全不知道。后来我加了一条规则:CRC 场的位错误注入,必须同时监控错误帧计数器和重发次数。

3.3 CRC 错误注入

CRC 错误,是 CAN 协议中用于检测数据完整性的机制。接收节点计算 CRC 并与发送值比较,不一致就丢弃报文。嗯,这里要注意:CRC 错误不会触发错误帧,只是报文被静默丢弃。

注入方式

  1. 修改 CRC 场:在报文发送前,用工具将 CRC 场的值改为任意错误值。
  2. 破坏数据场:修改数据场的某个字节,但不重新计算 CRC,导致接收端 CRC 校验失败。
  3. 注入 CRC 边界值:测试 CRC 全 0、全 1 或随机值,验证接收节点的容错能力。
CRC 注入类型 预期结果 测试优先级
单比特 CRC 错误 报文被丢弃,节点请求重发 高
多比特 CRC 错误 报文被丢弃,可能触发错误帧 中
CRC 全 0 接收节点应能识别并丢弃 低
CRC 全 1 接收节点应能识别并丢弃 低
关键点:CRC 错误注入后,要观察应用层是否收到了错误报文。如果应用层收到了 CRC 错误的报文,说明接收节点的 CRC 校验逻辑有 bug。我在一个项目中就遇到过,接收节点在特定条件下跳过了 CRC 校验,直接使用了错误数据。

3.4 信号超时注入

信号超时,是应用层最关心的故障。ECU 在规定时间内没收到预期报文,就判定信号超时。线控转向中,转向角信号超时超过 10ms,系统就必须进入安全状态。

注入策略

  • 完全丢帧:停止发送某条报文,模拟发送节点死机。
  • 延迟发送:将报文发送时间推迟到超时阈值之后(如正常周期 10ms,延迟到 15ms 发送)。
  • 周期抖动:随机改变报文发送周期,模拟总线负载波动导致的延迟。
我的建议:信号超时测试一定要做“临界值测试”。比如超时阈值是 100ms,你就分别注入 99ms、100ms、101ms 的延迟。我见过一个系统,99ms 延迟正常,101ms 延迟就报超时,但 100ms 延迟时系统状态不确定——这就是典型的边界问题。

测试矩阵示例

信号名称 正常周期 超时阈值 注入延迟 预期行为
转向角信号 10ms 20ms 25ms 进入降级模式,使用预测值
扭矩请求 5ms 10ms 12ms 切换到冗余传感器
状态报文 100ms 200ms 210ms 记录 DTC,保持当前状态
警告:信号超时注入时,要同时监控多个接收节点。我曾经在测试中只关注了主控制器,结果发现冗余控制器也收到了超时信号,两个控制器同时切换,导致系统震荡。后来我加了一条规则:超时注入必须覆盖所有接收节点。

3.5 知识体系总览

下面这张图,把四种总线故障注入的核心逻辑串起来了。你可以把它当作测试时的“作战地图”。

CAN/LIN 总线故障注入知识体系 CAN/LIN 总线故障注入核心逻辑 总线 off 位错误 CRC 错误 信号超时 故障注入执行层 协议层响应 应用层行为 诊断记录 测试闭环:注入 → 观察 → 分析 → 修复 → 回归 每种故障注入都要覆盖正常、边界、异常三种场景 记录每次注入的精确时间戳和系统响应

四种故障类型,覆盖了从物理层到应用层的所有通信故障模型。总线 off 和位错误属于物理层,CRC 错误属于数据链路层,信号超时属于应用层。测试时,我建议按这个顺序来:先做信号超时(最简单),再做 CRC 错误,然后做位错误,最后做总线 off(破坏性最大)。

总结:总线故障注入的核心,是验证系统在通信异常时的行为是否符合安全目标。不要只测“能不能恢复”,还要测“恢复过程中会不会产生危险”。记住,线控转向没有机械备份,总线就是生命线。