CAN 总线诊断帧的解析与异常重试
UDS 多帧传输(ISO-TP)在总线负载高时容易丢帧,而诊断仪通常不会告诉你丢在哪一帧。
分段重组的边界
首帧给出总长度,后续连续帧按序号递增。关键是序号回绕:
sn = (sn + 1) & 0x0F; // 0..15 循环
如果收到的序号不连续,说明中间丢帧,必须整条消息丢弃重传,而不是拼接——否则会得到一条看似完整但内容错位的数据。
超时判定
ISO-TP 标准规定连续帧间隔超过 1000ms 判超时,但实测在 60% 负载下这个值太宽松,会导致上层等待过久。我们改成 250ms,同时把 STmin 协商到 10ms。
幂等重试
重试最怕的是"其实已经成功但响应丢了",重发会造成重复执行。解决方法是在请求里带序列号,ECU 侧做去重:
- 每个诊断请求分配单调递增的
seq - ECU 缓存最近 8 个
seq - 重复
seq直接返回上次结果,不重复执行
这样重试就是安全的,最多浪费一次总线带宽。