CAN 错误帧、错误计数与 Bus-Off:节点出错如何自恢复
更新时间:2026-09-19。前置:CAN 总线协议、CAN FD。CAN 以高可靠著称,核心机制之一就是每个节点实时统计自己的发送/接收错误,逐步「自我隔离」,最终把持续故障节点踢下总线,保护其余节点。
本文要回答的问题
- CAN 检测错误后发的错误帧长什么样?
- TEC/REC 在什么情况下加/减,怎样跨越三个状态?
- 什么条件进入 Bus-Off,标准恢复序列是什么?
- 为什么好节点也可能频繁报错,采样点/终端电阻怎么影响?
一、五类错误检测
CAN 在多个环节同时查错:
- 位错误(Bit Error):发送方在总线上读到的电平与自己发出的不一致(仲裁场丢失仲裁、ACK 槽除外)。
- 填充错误(Stuff Error):连续 5 个同极性位后第 6 位没有自动取反(违反位填充)。
- CRC 错误:算出的 CRC 与收到的不符。
- 格式错误(Form Error):CRC/ACK/EOF 等固定格式位出现非法电平。
- ACK 错误(Acknowledgement Error):发送方在 ACK 槽没听到任何接收方拉的显性位(没人正确收到)。
检测到错误的节点立即破坏当前帧:发送错误帧。
二、错误帧结构
错误帧由两部分组成:
错误标志(Error Flag) + 错误界定符(Error Delimiter)- 主动错误标志:处于 Error-Active 的节点连续发 6 个显性位,故意制造位填充/格式违例,让所有节点都知道出错并丢弃当前帧。
- 被动错误标志:处于 Error-Passive 的节点发 6 个隐性位(除非被别人显性覆盖),尽量不影响总线。
- 错误界定符:8 个隐性位;之后节点等待总线出现隐性跳变,重新参与下一次通信。
收到错误标志后,发送方按规则重发该帧(CAN 自动重传)。
三、TEC/REC 与三个错误状态
每个节点维护 **TEC(发送错误计数器)**和 REC(接收错误计数器),按标准的「故障界定(fault confinement)」规则增减(简化):
- 发送一帧出错(自己发的):TEC +8;成功发一帧并收到 ACK:TEC -1。
- 接收一帧检测到错误:REC +8;成功收一帧:REC -1(被动状态下规则略不同)。
- 主动错误标志导致的错误,相关节点加 8;被动节点发送后还有额外 +8 等细则。
据此划三态:
TEC < 128 且 REC < 128 → Error-Active(错误主动,正常态,可发主动错误标志)
TEC ≥ 128 或 REC ≥ 128 → Error-Passive(错误被动,只能发被动标志,发送后要等额外挂起时间)
TEC ≥ 256 → Bus-Off(总线关闭,脱离总线,不收不发)
REC ≥ 256 仍停留在 Error-Passive(接收方不进 Bus-Off,因为它不会干扰总线)
计数降到阈值下并满足条件可回退状态设计意图:偶发错误只小幅累加、成功通信就衰减;持续发错(往往是自身故障,如驱动器坏)的节点 TEC 涨得快,最终 Bus-Off 自我隔离;而只接收出错(可能是别人在干扰)的节点不会被永久踢出。
四、Bus-Off 恢复序列
进入 Bus-Off 后,标准恢复条件:
节点检测到 128 次出现 11 个连续隐性位(即总线空闲) → 清 TEC/REC → 回到 Error-Active
(等价于在总线上观察到足够长时间的空闲/正常通信)- 多数 CAN 控制器提供寄存器配置:自动恢复(检测到 128×11 隐性位后自动回总线)或手动恢复(软件干预后才恢复,避免坏节点反复冲击总线)。
- 恢复计数器、错误中断、最近错误码(LEC)用于诊断。安全应用常在 Bus-Off 后先做有限次自动恢复 + 报警,持续失败则保持离线、记录故障并进入安全态(与 时钟失效切换 的 fail-safe 思路一致)。
- 注意:Bus-Off 期间该节点的报文全部停发,上层要有超时检测。
五、为什么好节点也报错(物理层主因)
很多 Bus-Off 不是协议栈 bug 而是物理层:
- 终端电阻:CAN 两端应各有一个 120Ω(等效 60Ω)。缺失/多余/不匹配造成反射,特定波特率/报文模式下采样出错,TEC 持续上升 → Bus-Off。
- 采样点(sample point):位时间中采样位置配置不当(常见推荐 75%~87.5%)、SJW/传播段不合理,遇到轻微抖动就采错。CAN FD 速率更高,采样点和收发器延迟更敏感(见 CAN FD BRS)。
- 波特率偏差大、节点共地差、支线过长、收发器供电异常、单总线断裂:都会让某节点或全部节点频繁 CRC/位错误。
- 只有一个节点反复 Bus-Off 而其他正常,多半是那个节点的收发器/供电/波特率问题;全部节点都报错则查总线终端和公共地。
六、常见的坑
- 把 Bus-Off 当普通丢帧:Bus-Off 后完全不收不发,必须有恢复+上层超时,否则功能静默失效。
- 无脑无限自动恢复:真正硬件故障的节点反复上线冲击总线;应限次+报警/安全态。
- 错误计数规则理解错:接收方 REC≥256 不会 Bus-Off;只有发送方 TEC≥256 才离线。
- 忽略错误中断只看数据:偶发被动态是 SI/时钟恶化的早期信号,应统计而非屏蔽。
- 采样点/位时序配错:能通信但高负载或温度变化时频繁错帧。
- 终端电阻数量错:只在一端加、或每个节点都加,反射/过载导致错误。
- 波特率容差超限:多个节点晶振误差叠加,长帧尾部采样漂移。
- 把仲裁失败当位错误计数:仲裁场正常丢失不算故障,控制器不应增加 TEC(实现要正确区分)。
- 被动状态发送延迟未处理:Error-Passive 发送后额外挂起时间影响周期,实时性受影响。
- CAN/CAN FD 错误规则混用:FD 帧 CRC/ stuff 位更多,错误现象与 Classical 不完全相同。
- 共模/地偏移:两节点不共地或长距离共模超范围,收发器误判电平。
- 单节点无 ACK:总线上只有一个能节点时,发帧必 ACK 错误、TEC 上涨,调试时要至少两个正常节点或回环模式。
相关与延伸
帧格式与非破坏性仲裁见 CAN 协议;速率升级见 CAN FD;车载低速总线见 LIN;差分信号与 SI 见 片上信号完整性。
总结
CAN 的容错靠每节点的 TEC/REC 两个错误计数器:检测到位/填充/CRC/格式/ACK 五类错误之一就主动发 6 个显性位的错误帧破坏当前报文并触发重传,自身发送出错 TEC+8、成功则-1,接收错误 REC+8;计数低于 128 为正常的 Error-Active,达到 128 降为只能发隐性错误标志、发送带额外挂起的 Error-Passive,TEC 到 256 即 Bus-Off 彻底脱离总线,再靠观察到 128 次「11 个连续隐性位」按自动或手动策略恢复——这样持续自身故障的节点被自我隔离、只接收受干扰的节点不被踢出;工程上多数莫名 Bus-Off 来自终端电阻、采样点和共模问题而非协议逻辑,单节点无 ACK 必报错是调试常识。