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收发器的共模电压范围不够,导致在强电磁干扰下信号畸变。换了一款工业级的收发器,问题就解决了。
这里我给大家几个建议:
- 不要忽视错误计数器:很多工程师只看有没有通信,不看错误计数器的值。我建议你在诊断协议里把TEC和REC读出来,作为健康监测指标。
- Bus Off恢复策略要谨慎:有些芯片支持快速恢复,但我不建议你用。让节点老老实实等待128次总线空闲,这是最稳妥的做法。
- 错误被动状态要警惕:节点进入错误被动后,虽然还能通信,但性能已经下降了。这时候应该触发一个故障码,提醒系统做降级处理。
- 硬件设计要留余量:CAN总线的共模电压范围、终端电阻匹配、线缆屏蔽,这些都会影响错误率。别为了省几毛钱,让整个系统不稳定。
嗯,关于CAN错误处理与故障界定,今天就聊到这里。下一章咱们讲讲CAN的位时序与同步机制,这可是理解CAN通信质量的关键。到时候见。