4. CAN错误处理与故障界定:错误类型、错误计数器、故障界定状态机

大家好,我是老周。今天咱们聊聊CAN总线里一个特别重要、但很多人容易忽略的话题——错误处理与故障界定。

说实话,我刚入行那会儿,觉得CAN通信嘛,只要硬件连对了,软件配置好,数据就能跑起来。直到有一次,我在一个ADAS项目里,车子跑到一半,ECU突然“罢工”了。排查了三天,最后发现是CAN控制器把自己给“关禁闭”了——进入了Bus Off状态。从那以后,我深刻意识到:不懂错误处理机制,你根本算不上懂CAN。

4.1 错误类型:CAN总线上的“五宗罪”

CAN协议定义了五种错误类型。说白了,就是总线上的节点如果发现不对劲,就会报错。我习惯把这五种错误称为“五宗罪”,咱们一个一个来看。

4.1.1 位错误(Bit Error)

这个最好理解。节点往总线上发了一个“显性”位(逻辑0),结果自己回读的时候发现总线上是“隐性”位(逻辑1)。这就叫位错误。

关键点:只有发送节点才会检测到位错误。接收节点不会报这个错。

我在项目中遇到过一种情况:总线终端电阻没匹配好,导致信号反射,发送节点老是读到错误的电平。嗯,这种硬件问题排查起来最头疼。

4.1.2 填充错误(Stuff Error)

CAN协议规定:连续发送5个相同电平的位之后,必须插入一个相反电平的位。这叫“位填充”。如果接收方发现连续6个相同电平的位,那就报填充错误。

你想想看,为什么要这么设计?说白了就是为了保证时钟同步。没有位填充,接收方可能就“跟丢”了节奏。

小提示:CRC界定符、ACK界定符、EOF这些字段是不进行位填充的。别搞混了。

4.1.3 格式错误(Form Error)

这个更简单。如果某个帧的固定格式字段(比如CRC界定符、ACK界定符)出现了错误电平,就报格式错误。

我记得有一次,一个供应商的CAN控制器芯片有bug,在发送EOF时少发了一个隐性位,结果整个网络上的节点都在报格式错误。那场面,真是“一人犯错,全网遭殃”。

4.1.4 应答错误(ACK Error)

发送节点在ACK Slot期间没有检测到显性位,就认为没有节点正确接收,于是报应答错误。

为什么会这样?可能是总线上只有一个节点在发,没有其他节点应答。也可能是接收节点的验收滤波没配好,直接把报文给“过滤”掉了。

4.1.5 CRC错误

接收节点计算出来的CRC校验值,跟发送节点发过来的CRC值对不上。这是最常见的错误类型之一。

我建议你在做CAN通信测试时,重点关注CRC错误。因为很多电磁干扰、信号质量问题,都会首先体现在CRC错误上。

错误类型 谁检测 常见原因
位错误 发送节点 总线竞争、硬件故障
填充错误 所有节点 位填充规则被破坏
格式错误 所有节点 固定格式字段异常
应答错误 发送节点 无节点应答
CRC错误 接收节点 数据被干扰

4.2 错误计数器:CAN控制器的“记分牌”

每个CAN控制器内部都有两个计数器:发送错误计数器(TEC)和接收错误计数器(REC)。

说白了,这就是一个“记分牌”。你表现好,分数就降;你表现差,分数就涨。

4.2.1 计数规则

  • 发送节点:每检测到一个错误,TEC加8。成功发送一次,TEC减1。
  • 接收节点:每检测到一个错误,REC加1。成功接收一次,REC减1。

这里有个细节:如果发送节点检测到应答错误或位错误,TEC加8。但如果发送节点检测到填充错误、格式错误或CRC错误,TEC不加。为什么?因为这些错误可能是发送节点自己造成的,也可能是其他节点造成的。CAN协议的设计者认为,发送节点不应该为别人的错误“背锅”。

注意:当TEC或REC超过127时,节点会进入“错误被动”状态。当TEC超过255时,节点会进入“Bus Off”状态。

4.3 故障界定状态机:从“好学生”到“关禁闭”

CAN控制器根据TEC和REC的值,定义了三种状态:错误主动、错误被动、Bus Off。

我习惯把这三种状态比作学生的三种表现:

  • 错误主动(Error Active):好学生。可以正常发送和接收,发现错误时发送“主动错误帧”。
  • 错误被动(Error Passive):差学生。可以发送和接收,但发现错误时只能发送“被动错误帧”。而且发送完一个报文后,必须等待8个隐性位才能继续发送。
  • Bus Off:被开除。不能发送任何报文,只能“听”。

4.3.1 状态转换条件

咱们用一张表说清楚:

当前状态 转换条件 下一状态
错误主动 TEC > 127 或 REC > 127 错误被动
错误被动 TEC 和 REC 都 ≤ 127 错误主动
错误被动 TEC > 255 Bus Off
Bus Off 检测到128次11个连续的隐性位 错误主动

重要:从Bus Off恢复到错误主动,需要检测到128次总线空闲(11个连续的隐性位)。这个过程通常由硬件自动完成,但有些芯片需要软件参与。

4.4 避坑指南:我踩过的那些坑

讲了这么多理论,咱们来点实战经验。

我曾经踩过一个坑:在一个项目中,某个ECU频繁进入Bus Off状态。排查了很久,发现是CAN收发器的共模电压范围不够,导致在强电磁干扰下信号畸变。换了一款工业级的收发器,问题就解决了。

这里我给大家几个建议:

  1. 不要忽视错误计数器:很多工程师只看有没有通信,不看错误计数器的值。我建议你在诊断协议里把TEC和REC读出来,作为健康监测指标。
  2. Bus Off恢复策略要谨慎:有些芯片支持快速恢复,但我不建议你用。让节点老老实实等待128次总线空闲,这是最稳妥的做法。
  3. 错误被动状态要警惕:节点进入错误被动后,虽然还能通信,但性能已经下降了。这时候应该触发一个故障码,提醒系统做降级处理。
  4. 硬件设计要留余量:CAN总线的共模电压范围、终端电阻匹配、线缆屏蔽,这些都会影响错误率。别为了省几毛钱,让整个系统不稳定。

嗯,关于CAN错误处理与故障界定,今天就聊到这里。下一章咱们讲讲CAN的位时序与同步机制,这可是理解CAN通信质量的关键。到时候见。