4. CAN网络常见故障分类
大家好,我是老周。今天咱们聊聊CAN总线里一个特别实在的话题——错误处理。
很多人觉得CAN通信只要硬件连对了、波特率配好了,就能稳定跑。其实不然。我见过太多项目,前期调试一切正常,一上整车或者进到强干扰环境,总线就开始“抽风”。这时候如果你不懂CAN的错误处理机制,排查起来就像无头苍蝇。
说白了,CAN总线之所以能在工业、汽车领域活这么久,靠的就是这套健壮的错误检测与恢复机制。今天我就把这套机制掰开揉碎了讲给你听。
4.1 五种错误类型:CAN的“安检系统”
CAN协议定义了五种错误类型。任何一个CAN节点在发送或接收报文时,都会实时检查这五类错误。一旦发现,节点就会主动发出错误帧。
| 错误类型 | 检测时机 | 检测节点 | 触发条件 |
|---|---|---|---|
| 位错误 | 发送时 | 发送节点 | 发送位与总线电平不一致(仲裁场和应答场除外) |
| 填充错误 | 接收时 | 所有节点 | 连续6个相同电平出现(违反位填充规则) |
| CRC错误 | 接收时 | 接收节点 | 计算CRC与发送CRC不匹配 |
| 格式错误 | 接收时 | 所有节点 | 帧格式固定位域出现非法电平 |
| 应答错误 | 发送时 | 发送节点 | 应答间隙未检测到显性位 |
4.1.1 位错误
这个最直观。发送节点往总线上放一个位,同时回读总线电平。如果读回来的和自己发的不一样,那就是位错误。
但有两个例外:仲裁场和应答场。仲裁时多个节点同时发,显性位覆盖隐性位是正常现象。应答时发送节点发隐性位,接收节点拉成显性位,这也是正常的。
实战经验:我遇到过一台ECU,位错误计数器疯狂增长。查了半天,发现是CAN收发器的共模电压出了问题,导致发送节点读回的电平失真。换了个收发器,问题解决。
4.1.2 填充错误
CAN协议规定:连续发送5个相同电平后,必须插入一个相反电平。这叫位填充。
如果接收节点发现连续6个相同电平,那就说明填充规则被破坏了。这通常意味着总线受到了强干扰,或者某个节点的发送时序出了问题。
小技巧:用示波器抓CAN总线波形时,看到连续6个以上相同电平的段,基本可以断定总线有填充错误。这是快速定位物理层问题的好方法。
4.1.3 CRC错误
CRC(循环冗余校验)是CAN帧的“指纹”。发送节点计算15位CRC放在帧里,接收节点重新计算一遍。对不上,就是CRC错误。
CRC错误的常见原因:
- 总线干扰导致数据位翻转
- 波特率配置偏差
- CAN控制器时钟精度不够
4.1.4 格式错误
CAN帧的某些位域是固定电平。比如CRC界定符必须是隐性位,ACK界定符也必须是隐性位。如果这些地方出现了显性位,那就是格式错误。
格式错误通常意味着:
- 某个节点发送了格式异常的帧
- 总线电平被长时间拉低
- CAN控制器硬件故障
4.1.5 应答错误
发送节点在ACK间隙发送隐性位,期望至少有一个接收节点把它拉成显性位。如果没人拉,那就是应答错误。
应答错误的典型场景:
- 总线上没有其他节点在监听
- 接收节点的验收滤波把报文过滤掉了
- 接收节点处于总线关闭状态
注意:应答错误不等于总线断开了。我曾经排查过一个案例,总线明明连着两个节点,但其中一个就是收不到报文。最后发现是验收滤波配置错了,报文ID被过滤掉了。发送节点一直报应答错误,但物理层是完好的。
4.2 错误状态机:节点的“三色灯”
每个CAN节点内部都有一个错误状态机,根据错误计数器值切换状态。说白了,就是给节点装了三个档位:
4.2.1 错误主动(Error Active)
这是正常状态。节点可以正常收发报文。发现错误时,发送主动错误标志——连续6个显性位。这个标志会强制打断当前总线上的通信,让所有节点都知道出错了。
4.2.2 错误被动(Error Passive)
当接收错误计数器(REC)或发送错误计数器(TEC)超过127时,节点进入错误被动状态。
这个状态下,节点仍然可以收发报文,但发现错误时只能发送被动错误标志——连续6个隐性位。说白了,就是“我发现了错误,但我没能力打断总线”。
我踩过的坑:有一次调试,一个节点频繁进入错误被动状态。它发的被动错误标志是隐性位,其他节点根本感知不到。结果这个节点一直在发错误帧,但总线上其他节点完全不知道。最后用CAN分析仪抓包才发现,这个节点的TEC已经飙到200多了。
4.2.3 总线关闭(Bus Off)
当TEC超过255时,节点进入总线关闭状态。这个节点彻底脱离总线,不再参与任何通信。它既不发报文,也不发错误帧,完全“沉默”。
要恢复,节点需要检测到128次连续的11个隐性位(总线空闲状态)。这通常由硬件自动完成,但有些CAN控制器需要软件干预。
4.3 错误计数器:节点的“记分牌”
每个CAN节点有两个错误计数器:
- TEC(Transmit Error Counter):发送错误计数器
- REC(Receive Error Counter):接收错误计数器
计数器的增减规则很有意思,我直接给你列个表:
| 事件 | TEC变化 | REC变化 |
|---|---|---|
| 发送节点检测到位错误 | +8 | 不变 |
| 发送节点检测到应答错误 | +8 | 不变 |
| 发送节点检测到格式错误 | +8 | 不变 |
| 接收节点检测到错误 | 不变 | +1 |
| 发送节点成功发送 | -1 | 不变 |
| 接收节点成功接收 | 不变 | -1(若REC > 0) |
| 错误被动节点发送成功 | -1 | 不变 |
| 错误被动节点接收成功 | 不变 | -1(若REC > 127) |
你看这个设计很有意思:
- 加罚重:发现一次错误加8分,成功一次只减1分。这就保证了有问题的节点会快速被“隔离”。
- 发送错误罚得更狠:发送错误一次加8,接收错误一次只加1。因为发送错误通常意味着节点本身有问题。
- 减分有下限:计数器不会减到负数,最低是0。
实用技巧:诊断CAN总线问题时,我第一件事就是读每个节点的TEC和REC值。如果某个节点的TEC持续增长,那基本可以锁定它就是总线问题的“元凶”。如果所有节点的REC都在涨,那问题大概率出在物理层——比如终端电阻、线缆屏蔽或者共模干扰。
4.4 错误帧结构
当节点检测到错误时,会发送错误帧。错误帧由两部分组成:
- 错误标志:6个连续相同电平
- 错误主动节点:6个显性位
- 错误被动节点:6个隐性位
- 错误界定符:8个隐性位
错误帧的优先级高于数据帧和远程帧。一旦有节点发出错误帧,总线上的所有节点都会检测到位填充错误(连续6个相同电平),然后各自发送自己的错误标志。这就形成了所谓的“错误帧叠加”——总线上会出现6-12个显性位。
重要提醒:错误帧叠加是CAN总线的一种自我保护机制。它确保所有节点都能感知到错误,并丢弃当前正在传输的报文。但这也意味着,如果总线错误频繁发生,有效带宽会大幅下降。我见过一个极端案例,总线利用率只有5%,剩下的95%都在发错误帧。
4.5 实战排查思路
最后,我总结一下遇到CAN总线错误时的排查思路:
- 读错误计数器:用CAN分析仪或诊断工具读每个节点的TEC和REC。
- 看错误类型分布:哪种错误最多?
- 位错误多 → 检查物理层(终端电阻、线缆、收发器)
- CRC错误多 → 检查波特率精度、总线干扰
- 填充错误多 → 检查总线噪声、节点时序
- 格式错误多 → 检查CAN控制器配置、硬件故障
- 应答错误多 → 检查节点数量、验收滤波配置
- 定位问题节点:TEC持续增长的节点就是“嫌疑犯”。
- 抓波形:用示波器看CAN_H和CAN_L的差分信号,确认物理层质量。
嗯,这套方法我用了十几年,基本没失手过。你只要把错误类型、状态机和计数器这三块吃透了,CAN总线故障排查就成功了一半。