CAN错误处理机制:错误计数、错误状态和总线关闭

CAN 被广泛用于汽车和工业现场,一个重要原因是它不只是“能通信”,还很擅长“发现通信出问题了”。
在复杂现场里,干扰、接触不良、波特率不一致、终端电阻错误、节点异常发送都可能让报文出错。CAN 协议没有把这些问题交给应用层自己猜,而是在底层设计了完整的错误检测和错误状态管理机制。
这一篇我们聊 CAN 的错误处理:ACK 错误、CRC 错误、位错误、填充错误、格式错误,以及错误计数、主动错误、被动错误和 Bus-Off。
一、CAN为什么需要错误处理机制?
在控制系统里,错误数据比没有数据更危险。
比如:
- 电池电压被错误解析;
- 电机控制指令被干扰;
- 制动状态报文传输异常;
- 传感器数据偶发跳变;
- 某个坏节点一直占用总线。
如果协议层不检测错误,上层应用可能会把错误数据当成正常数据使用。
CAN 的思路是:尽早发现错误,通知其他节点,必要时限制异常节点继续影响总线。
这套机制让 CAN 很适合可靠性要求较高的控制网络。
二、CAN常见错误类型

CAN 协议定义了多种错误检测方式。常见错误包括:
- 位错误;
- 填充错误;
- CRC 错误;
- 格式错误;
- ACK 错误。
每种错误对应不同问题,理解它们有助于定位故障。
三、位错误:发出去和读回来不一样
CAN 节点发送报文时,会同时监听总线。
如果节点发送了某个位,但从总线上读到的结果和预期不一致,就可能触发位错误。
不过仲裁阶段有例外。
在仲裁阶段,如果节点发送隐性位 1,却读到显性位 0,这代表自己仲裁失败,并不是位错误。
真正的位错误通常发生在仲裁之外的字段。
常见原因包括:
- 总线干扰严重;
- 收发器异常;
- CAN_H/CAN_L 短路或接触不良;
- 总线被异常节点拉住;
- 波形畸变导致电平判断错误。
四、填充错误:连续相同位太多
CAN 使用位填充机制。
为了保持同步,当发送端连续发送 5 个相同位后,会自动插入 1 个相反位。接收端收到后会把这个填充位去掉。
如果接收节点发现不符合位填充规则,就会报告填充错误。
填充错误常见于:
- 干扰导致某个位翻转;
- 波特率或采样点不匹配;
- 总线波形质量差;
- 节点时钟偏差过大。
位填充机制本来是为了帮助同步,但它也提供了一种错误检测方式。
五、CRC错误:校验结果不一致
CRC 错误比较直观。
发送端根据报文内容计算 CRC,接收端也计算一遍。如果两者不一致,说明报文在传输过程中可能被破坏。
CRC 错误通常说明数据位发生了错误,可能原因包括:
- 电磁干扰;
- 线缆质量差;
- 终端匹配不好;
- 支线太长;
- 波特率配置不合理;
- 收发器或连接器问题。
如果现场偶发 CRC 错误,不要只盯着代码,示波器和线缆检查往往更有价值。
六、格式错误:固定格式字段不对
CAN 帧中有些字段必须是固定格式,比如 CRC delimiter、ACK delimiter、EOF 等位置。
如果节点检测到这些固定字段不符合协议要求,就会产生格式错误。
格式错误可能来自:
- 总线干扰;
- 节点时序不同步;
- 错误帧叠加影响;
- 控制器或收发器异常;
- 非法波形被误识别。
格式错误不一定很常见,但一旦频繁出现,通常说明底层信号质量或节点配置存在明显问题。
七、ACK错误:没人确认收到
ACK 错误是调试中非常常见的一类错误。
发送节点发送一帧报文后,会在 ACK 槽等待其他节点应答。如果至少有一个节点正确收到该报文,它会在 ACK 槽发送显性位。
如果发送节点没有检测到 ACK,就会认为发生 ACK 错误。
常见原因包括:
- 总线上只有一个发送节点;
- 其他节点没有上电;
- 接收节点波特率不一致;
- 接收节点过滤器配置错误;
- CAN_H/CAN_L 接线错误;
- 收发器损坏;
- 发送节点和接收节点没有真正连在同一条总线上。
注意:过滤器配置是否影响 ACK,要看控制器实现和接收状态。很多情况下,节点只要在协议层正确接收该帧就会 ACK,即使应用层不处理。但如果节点因波特率、错误状态或硬件问题根本没有正确接收,就不会 ACK。
调试时如果一直 ACK 错误,先确认总线上有没有第二个正常节点。

八、错误帧:发现错误后通知全总线
当节点检测到错误时,会发送错误帧。
错误帧的作用是告诉总线上的其他节点:当前这帧有问题,不要把它当成有效报文。
这会让正在传输的报文失败,发送节点之后会尝试重发。
从可靠性角度看,这很重要。因为只要有节点发现错误,就应该让这帧作废,而不是让部分节点使用错误数据。

九、错误计数器:TEC 和 REC
CAN 控制器内部通常有两个错误计数器:
- TEC:Transmit Error Counter,发送错误计数器;
- REC:Receive Error Counter,接收错误计数器。
发送错误会影响 TEC,接收错误会影响 REC。
不同错误对计数器的增减规则并不完全相同,协议中有详细规定。入门阶段不用死背每条规则,先理解它的目的:
节点错误越多,错误计数越高;错误计数越高,节点状态越受限制。
这可以避免异常节点一直破坏总线。

十、三种错误状态
CAN 节点根据错误计数,大致会处于三种状态:
- Error Active,错误主动;
- Error Passive,错误被动;
- Bus-Off,总线关闭。
1. 错误主动
正常节点通常处于错误主动状态。
它可以正常发送和接收报文。如果检测到错误,会发送主动错误标志,强力通知总线当前报文无效。
2. 错误被动
当错误计数升高到一定程度,节点会进入错误被动状态。
错误被动节点仍然可以通信,但它报告错误的方式更温和,对总线影响更小。
这相当于协议层在说:“这个节点最近错误比较多,先降低它对总线的干扰能力。”
3. Bus-Off
当发送错误计数继续升高,节点可能进入 Bus-Off。
Bus-Off 状态下,节点会停止参与总线通信,既不发送也不干扰总线。
这是一种自我隔离机制,目的是保护总线上其他正常节点。

)
十一、Bus-Off常见原因
Bus-Off 是工程中很常见也很关键的问题。
常见触发原因包括:
- CAN_H/CAN_L 接反;
- 总线短路;
- 没有 ACK 节点;
- 波特率错误;
- 采样点配置不匹配;
- 终端电阻错误;
- 收发器损坏;
- 强干扰导致大量发送失败;
- 节点发送过快,总线持续异常。
如果一个节点刚启动就很快 Bus-Off,优先检查硬件连接、波特率和终端电阻。
十二、Bus-Off后怎么恢复?
Bus-Off 后是否自动恢复,取决于控制器配置和软件策略。
一些 CAN 控制器支持自动 Bus-Off 恢复,也可以由软件检测到 Bus-Off 后重新初始化 CAN 外设。
工程上要谨慎设计恢复策略。
如果只是偶发干扰,自动恢复很方便。
但如果硬件短路或波特率根本不对,盲目自动恢复会让节点反复上线、报错、下线,给系统诊断造成干扰。
比较稳妥的策略是:
- 记录 Bus-Off 事件;
- 停止发送一段时间;
- 检查关键状态;
- 尝试恢复 CAN 控制器;
- 限制恢复次数;
- 将故障上报给系统或诊断模块。
汽车和工业系统里,Bus-Off 通常不是一个可以悄悄忽略的小事。
十三、错误处理给调试带来的启发
看到 CAN 错误时,不要只问“代码哪里错了”,而要问“是哪一类错误”。
不同错误指向不同方向:
| 错误现象 | 优先排查方向 |
|---|---|
| ACK错误 | 是否有接收节点、波特率、接线、收发器 |
| CRC错误 | 干扰、线缆、终端电阻、波形质量 |
| 位错误 | 短路、异常节点、波形畸变 |
| 填充错误 | 时序、采样点、干扰 |
| Bus-Off | 大量发送失败、硬件连接、波特率错误 |
CAN 错误状态其实是协议在给你线索。
读懂这些线索,排查效率会高很多。

小结
CAN 的错误处理机制可以总结为:
- CAN 能检测多种传输错误;
- 错误节点会发送错误帧,让异常报文作废;
- TEC 和 REC 用来衡量节点错误程度;
- 节点状态包括错误主动、错误被动和 Bus-Off;
- Bus-Off 是节点自我隔离,避免持续破坏总线;
- ACK 错误常见于没有正常接收节点;
- CRC、位错误、填充错误往往和物理层质量相关。
CAN 的可靠性不是靠“永远不出错”,而是靠“能发现错误、限制错误、从错误中恢复”。
下一篇我们进入实战:以 STM32 为例,看看如何配置 CAN 波特率、过滤器、发送邮箱、接收 FIFO 和中断接收。
