📚 CAN总线技术系列 · 持续更新中
本系列从差分电气层一路打到 Linux SocketCAN,把"两根线"背后的电气/协议/控制器/驱动/实战全拧成一根线。
👉 想系统追更,戳这里查看完整专栏:
【CAN 技术系列】
👉 其他技术系列专栏,欢迎关注、交流、共同成长:
【SPI 技术系列】 【I2C 技术系列】 【串口技术系列】【RISC-V 架构系列】【Linux内核系列】 【操作系统设计思想系列】 【 Android 系统全景专栏】
本篇定位:CAN 协议层最强大的特性——错误处理。CAN 有 5 种错误检测、错误计数器、节点状态机(主动/被动/总线关闭)、错误帧自动破坏错帧。本篇讲清错误检测、错误帧、错误计数器、状态转移。读完你理解 CAN 为什么是汽车级可靠,以及总线关闭怎么恢复。
错误处理是 CAN 汽车级可靠的根基
SPI 无 ACK 无错误检测。I2C 只有 ACK/NACK。CAN 有 5 种错误检测 + 错误计数器 + 错误帧 + 自动重发 + 总线关闭——这是汽车级可靠的协议层保障。理解错误处理,才算懂 CAN。功能安全芯片,总线关闭恢复是必考。对照 [[10-SPI错误处理与恢复]] 和 [[10-I2C错误处理与恢复]] 看,CAN 的错误处理远比 SPI/I2C 完备。
目录
- 一、五种错误检测
- 1.1 位监控错误(Bit Monitoring)
- 1.2 位填充错误(Stuff Error)
- 1.3 CRC 错误(CRC Error)
- 1.4 格式错误(Form Error)
- 1.5 ACK 错误(ACK Error)
- 1.6 检测总结
- 二、错误帧
- 2.1 错误帧结构
- 2.2 主动错误标志(Active Error Flag)
- 2.3 被动错误标志(Passive Error Flag)
- 2.4 错误定界符(Error Delimiter)
- 2.5 错误帧作用
- 三、错误计数器
- 3.1 两个计数器
- 3.2 计数规则
- 3.3 计数器特性
- 3.4 计数器读取
- 四、节点状态机
- 4.1 三种状态
- 4.2 状态转移
- 4.3 主动错误(Error Active)
- 4.4 被动错误(Error Passive)
- 4.5 总线关闭(Bus-Off)
- 五、自动重发
- 5.1 自动重发机制
- 5.2 重发时机
- 5.3 单次发送模式
- 5.4 重发的问题
- 六、总线关闭恢复
- 6.1 总线关闭状态
- 6.2 自动恢复
- 6.3 软件恢复
- 6.4 恢复策略
- 6.5 功能安全考量
- 七、错误中断与处理
- 7.1 错误中断源
- 7.2 错误处理流程
- 7.3 错误统计
- 八、关键问题 Q&A
- Q1:CAN 五种错误检测分别什么时候触发?
- Q2:错误计数器怎么涨?为什么错+8 成功-1?
- Q3:主动错误和被动错误有什么区别?
- Q4:总线关闭怎么恢复?
- Q5:CAN 自动重发,什么时候停?
- Q6:错误计数器怎么看?
- 九、实战案例
- 案例 1:总线关闭,节点失联
- 案例 2:错误被动,通信降级
- 案例 3:ACK 错误,单节点自测
- 案例 4:EMI 导致位填充错误
- 案例 5:总线关闭无限恢复循环
- 案例 6:高优先级帧重发,低优先级饿死
- 案例 7:CRC 错误,采样点不一致
- 案例 8:格式错误,EOF 被干扰
- 十、本篇小结与速查
- 核心要点
- 错误检测速查
- 状态机速查
- 错误处理流程
- 功能安全 CAN 错误处理清单
- 延伸阅读
- 参考资料
一、五种错误检测
CAN 有 5 种硬件错误检测,覆盖位级到帧级:
1.1 位监控错误(Bit Monitoring)
- 节点发的位,读回总线比对
- 发显性读到隐性 / 发隐性读到显性(除仲裁区隐性读显性是输)
- 不符 → 位错误
1.2 位填充错误(Stuff Error)
- 连续 5 同电平后必须有填充位(反向)
- 6 个连续同电平 → 位填充错误
1.3 CRC 错误(CRC Error)
- 接收方重算 CRC,和发送方比对
- 不符 → CRC 错误
1.4 格式错误(Form Error)
- 固定格式的位(CRC界定符/ACK界定符/EOF/IFS)应为隐性
- 这些位出现显性 → 格式错误
1.5 ACK 错误(ACK Error)
- 发送方在 ACK 间隙发隐性
- 读到隐性(无节点应答)→ ACK 错误
1.6 检测总结
| 错误 | 检测方 | 时机 |
|---|---|---|
| 位监控 | 发送方 | 每个发位 |
| 位填充 | 接收方 | 仲裁段+CRC前 |
| CRC | 接收方 | CRC段 |
| 格式 | 接收方 | 定界符/EOF/IFS |
| ACK | 发送方 | ACK间隙 |
二、错误帧
2.1 错误帧结构
错误标志(6位) + 错误定界符(8位隐性)2.2 主动错误标志(Active Error Flag)
- 主动错误节点发:6 个连续显性位
- 破坏当前帧(覆盖数据,所有节点检测到错误)
- 6 个显性可能被其他错误节点叠加,变长(< 12 位)
2.3 被动错误标志(Passive Error Flag)
- 被动错误节点发:6 个连续隐性位
- 不强制破坏当前帧(隐性不覆盖)
- 其他节点可能正常接收,被动节点自己退出
2.4 错误定界符(Error Delimiter)
- 8 个连续隐性位
- 错误帧结束
- 之后总线闲,可重发
2.5 错误帧作用
- 检测到错误的节点发错误帧
- 主动错误帧破坏当前帧,所有节点丢弃
- 发送方重发(自动)
三、错误计数器
3.1 两个计数器
| 计数器 | 含义 |
|---|---|
| TEC(Transmit Error Counter) | 发送错误计数 |
| REC(Receive Error Counter) | 接收错误计数 |
3.2 计数规则
发送方:
- 发送错(ACK错/位错)→ TEC +8
- 发送成功 → TEC -1(到 0 为止)
接收方:
- 接收错(CRC/格式/填充)→ REC +8
- 接收成功 → REC -1(到 0 为止)
主动错误标志期间:
- 检测到显性位(其他节点也错)→ TEC/REC +1(少加,因为是别人错)
3.3 计数器特性
- 错误增 8,成功减 1(错比对影响大)
- 设计:偶发错误快速恢复,持续错误快速降级
- 范围:0~255
3.4 计数器读取
- 控制器寄存器(STM32 CAN_ESR 的 TEC/REC 字段)
- Linux:
ip -s link show can0看错误统计 - 调试必看
四、节点状态机
4.1 三种状态
| 状态 | TEC/REC | 行为 |
|---|---|---|
| 主动错误(Error Active) | < 96 | 正常 + 主动错误标志(6显性) |
| 被动错误(Error Passive) | 96~127 | 通信 + 被动错误标志(6隐性) + 帧间多等 |
| 总线关闭(Bus-Off) | TEC ≥ 128 | 不通信(完全隔离) |
4.2 状态转移
TEC/REC < 96 ┌─────────────────────┐ ↓ │ ┌─────────────┐ TEC/REC ≥ 96 ┌─────────────┐ │ 主动错误 │ ────────────→ │ 被动错误 │ │ (Error Active)│ │ (Error Passive)│ └─────────────┘ ←──────────── └─────────────┘ ↑ │ TEC/REC < 128(恢复) │ │ └──────────────────────────┘ │ │ │ TEC ≥ 128 │ TEC ≥ 255 │ (持续错误) ↓ │ ┌─────────────┐ │ │ 总线关闭 │ │ │ (Bus-Off) │ │ └─────────────┘ │ │ │ 恢复(128×11显性)│ └──────────────────┘4.3 主动错误(Error Active)
- 正常状态,通信正常
- 错误时发主动错误标志(6 显性,破坏当前帧)
- TEC/REC < 96
4.4 被动错误(Error Passive)
- 通信仍进行,但降级
- 错误时发被动错误标志(6 隐性,不破坏)
- 帧间隔多等 8 个隐性(挂起传输,降优先级)
- TEC/REC 96~127
4.5 总线关闭(Bus-Off)
- 完全不通信(隔离,保护总线)
- TEC ≥ 128(发送)或 TEC ≥ 255
- 需恢复(见下节)
- 功能安全关键状态
五、自动重发
5.1 自动重发机制
- 帧发送失败(ACK错/被错误帧破坏)→ 控制器自动重发
- 软件不感知(除非配置单次发送模式)
- 重发直到成功或总线关闭
5.2 重发时机
- 错误帧后,总线闲 + IFS(+ 被动状态多等 8 隐性)
- 重发参与仲裁(可能被更高优先级抢占)
5.3 单次发送模式
- 部分控制器支持(STM32 NART 位)
- 发一次不重发,软件处理
- 适用:实时性要求(超时丢弃)/ 测试
5.4 重发的问题
- 高优先级帧持续错 → 重发占总线 → 低优先级饿死
- 功能安全:重发次数限制(超限进安全状态)
六、总线关闭恢复
6.1 总线关闭状态
- TEC ≥ 128 → 总线关闭
- 节点完全不收发(隔离,避免持续错影响总线)
- 控制器进入 Bus-Off 状态
6.2 自动恢复
- 总线关闭后,检测到128 × 11 = 1408 个连续隐性位(约 11 帧时间)
- 自动回到主动错误状态(TEC/REC 清 0)
- 条件:总线有其他正常节点通信(产生隐性位)
6.3 软件恢复
- 部分控制器需软件触发恢复(退出 Bus-Off)
- STM32:清 ABOM 位 → 软件请求恢复
- Linux:
ip link set can0 up(重新启用)
6.4 恢复策略
| 策略 | 说明 |
|---|---|
| 自动恢复(ABOM) | 检测 1408 隐性自动恢复,推荐 |
| 软件恢复 | 软件检测 Bus-Off 后手动恢复 |
| 不恢复 | 锁死(功能安全降级,需人工干预) |
6.5 功能安全考量
- 总线关闭 = 节点故障,可能安全风险
- 恢复后要重新同步状态(应用层)
- AEGIX:总线关闭超阈值 → 进安全状态(不无限恢复)
总线关闭恢复是 AEGIX 功能安全必考
功能安全芯片 CAN 节点,总线关闭是故障状态。恢复策略:自动恢复(ABOM) + 恢复次数限制 + 超限进安全状态。不能无限恢复(可能硬件故障,继续通信危险)。恢复后应用层重新同步状态。这是功能安全审查重点。对照 [[10-SPI错误处理与恢复]] 的端到端保护,CAN 的总线关闭是协议层保护,SPI 要软件实现。
七、错误中断与处理
7.1 错误中断源
| 中断 | 触发 |
|---|---|
| 错误警告(EWGF) | TEC/REC ≥ 96(进被动) |
| 错误被动(EPVF) | TEC/REC ≥ 128 或从被动回主动 |
| 总线关闭(BOFF) | TEC ≥ 128(进 Bus-Off) |
| 最后错误码(LECN) | 上次错误类型(位/CRC/格式/ACK/填充) |
7.2 错误处理流程
voidcan_error_isr(void){uint32_tesr=CAN->ESR;if(esr&BOFF){// 总线关闭log_error("CAN Bus-Off");enter_safe_state();// 功能安全// 等自动恢复或软件恢复}if(esr&EPVF){// 错误被动log_warning("CAN Error Passive, TEC=%d REC=%d",(esr>>16)&0xFF,(esr>>24)&0xFF);}if(esr&EWGF){// 错误警告log_warning("CAN Error Warning");}uint8_tlec=(esr>>4)&0x7;switch(lec){case1:log_error("Stuff Error");break;case2:log_error("Form Error");break;case3:log_error("Ack Error");break;case4:log_error("Bit1 Error");break;case5:log_error("Bit0 Error");break;case6:log_error("CRC Error");break;}}7.3 错误统计
- Linux:
ip -s link show can0看 RX/TX 错误统计 - 实时监控错误计数器(TEC/REC)
- 错误日志记录(功能安全可追溯)
八、关键问题 Q&A
Q1:CAN 五种错误检测分别什么时候触发?
A:
- 位监控:发送方每发一位读回比对,不符(除仲裁区)
- 位填充:接收方看到 6 连续同电平(应 5+填充)
- CRC:接收方 CRC 不符
- 格式:固定隐性位(CRC/ACK 界定符/EOF/IFS)出现显性
- ACK:发送方 ACK 间隙读到隐性(无应答)
Q2:错误计数器怎么涨?为什么错+8 成功-1?
A:错+8,成功-1。设计意图:偶发错误快速恢复(1 次成功抵 1 次错),持续错误快速降级(8 次错进被动)。这样偶发噪声不致降级,持续故障快速隔离(被动→总线关闭)。
Q3:主动错误和被动错误有什么区别?
A:
- 主动错误(TEC/REC<96):错误标志 6 显性,破坏当前帧(所有节点丢弃)
- 被动错误(TEC/REC 96~127):错误标志 6 隐性,不破坏(其他节点可能正常接收),帧间多等 8 隐性(降优先级)
- 被动错误是降级状态,减少对总线影响
Q4:总线关闭怎么恢复?
A:
- 自动恢复(ABOM):检测 128×11=1408 连续隐性位,自动回主动错误(TEC/REC 清0)
- 软件恢复:软件检测 Bus-Off,手动请求恢复(Linux
ip link set can0 up) - 恢复条件:总线有其他正常节点(产生隐性位)
- 功能安全:恢复次数限制,超限进安全状态
Q5:CAN 自动重发,什么时候停?
A:持续重发直到:① 成功;② 总线关闭(TEC≥128,停止)。没有重发次数限制(除非单次发送模式 NART)。高优先级帧持续错会占总线,低优先级饿死。功能安全要软件限制(超时丢弃/进安全状态)。
Q6:错误计数器怎么看?
A:
- 裸机:读 CAN_ESR(STM32)的 TEC/REC 字段
- Linux:
ip -s link show can0看 RX/TX errors - 调试:逻辑分析仪抓错误帧,统计频率
- 功能安全:实时监控,超阈值告警
九、实战案例
案例 1:总线关闭,节点失联
现象:某节点 TEC 飙到 200,总线关闭,完全不通信。
分析:节点波特率配错(和全网不一致),发的帧别人采错(CRC错),ACK错,TEC 持续涨到 ≥128,总线关闭。
解决:修正波特率(和全网一致),总线关闭恢复(ABOM 自动或软件重启)。
案例 2:错误被动,通信降级
现象:节点 TEC 100(被动错误),通信时断时续。
分析:节点偶发位定时错(采样点偏),部分帧 CRC 错,TEC 涨到 96+ 进被动。
解决:修正位定时(采样点 87.5%),TEC 降到 96 以下,回主动错误。
案例 3:ACK 错误,单节点自测
现象:单节点测试,发送报 ACK 错误,TEC 涨。
分析:单节点无其他节点应答(ACK 间隙无显性),ACK 错,TEC 涨到总线关闭。
解决:单节点测试开 Loopback 模式(自收自发 ACK),或加另一节点。
案例 4:EMI 导致位填充错误
现象:CAN 总线偶发位填充错误,错误帧频发。
分析:EMI 让位翻转,连续同电平被破坏,位填充规则违反。
解决:加共模扼流圈 + TVS,远离干扰源,双绞屏蔽。
案例 5:总线关闭无限恢复循环
现象:节点总线关闭,自动恢复,又快速总线关闭,循环。
分析:节点硬件故障(收发器坏),恢复后发的帧错,TEC 快速涨又总线关闭。
解决:限制恢复次数(3 次后锁死),进安全状态,人工干预。
案例 6:高优先级帧重发,低优先级饿死
现象:高优先级帧(0x001)持续 ACK 错(目标节点故障),重发占总线,低优先级饿死。
分析:自动重发无次数限制,高优先级持续错占总线。
解决:单次发送模式(NART)或软件超时丢弃,目标节点故障进安全状态。
案例 7:CRC 错误,采样点不一致
现象:部分帧 CRC 错误,错误帧破坏,通信不稳。
分析:某节点采样点 75%,全网 87.5%,采错数据,CRC 不符。
解决:统一采样点 87.5%,CRC 错消失。
案例 8:格式错误,EOF 被干扰
现象:帧末格式错误(EOF 应隐性,出现显性),重发。
分析:EMI 在 EOF 期间干扰,显性混入隐性区。
解决:加抗扰措施(共模扼流圈/TVS/双绞),EOF 错误减少。
十、本篇小结与速查
核心要点
- CAN 五种错误检测:位监控/位填充/CRC/格式/ACK(硬件自动)
- 错误帧:主动错误(6显性,破坏)/被动错误(6隐性)+ 8 隐性定界
- 错误计数器:TEC(发送)/REC(接收),错+8 成功-1
- 节点状态:主动错误(<96)/被动错误(96~127)/总线关闭(≥128)
- 主动错误:正常通信,错误破坏当前帧;被动错误:降级,不破坏
- 总线关闭:完全隔离(不收发),保护总线
- 自动重发:帧错自动重发(无次数限制,除非 NART)
- 总线关闭恢复:128×11=1408 隐性位自动恢复 / 软件恢复
- 功能安全:恢复次数限制 + 超限进安全状态 + 恢复后重新同步
- 错误中断:BOFF/EPVF/EWGF/LEC,实时监控
错误检测速查
| 错误 | 检测方 | 触发 |
|---|---|---|
| 位监控 | 发送方 | 发≠读(除仲裁) |
| 位填充 | 接收方 | 6 连续同电平 |
| CRC | 接收方 | CRC 不符 |
| 格式 | 接收方 | 定界符/EOF 显性 |
| ACK | 发送方 | ACK 间隙隐性 |
状态机速查
| 状态 | TEC/REC | 行为 |
|---|---|---|
| 主动错误 | <96 | 正常 + 6显性错误标志 |
| 被动错误 | 96~127 | 降级 + 6隐性错误标志 |
| 总线关闭 | ≥128 | 隔离,不通信 |
错误处理流程
- 检测错误(5 种)
- 发错误帧(主动/被动)
- 错误计数器更新(TEC/REC)
- 状态转移(主动→被动→总线关闭)
- 自动重发(除非总线关闭)
- 总线关闭恢复(1408 隐性 / 软件)
- 功能安全:超限进安全状态
功能安全 CAN 错误处理清单
- 错误中断处理(BOFF/EPVF/EWGF)
- 错误计数器监控
- 总线关闭恢复策略(ABOM + 次数限制)
- 恢复超限进安全状态
- 恢复后应用层重新同步
- 错误日志记录(可追溯)
- 看门狗兜底
延伸阅读
- [[04-CAN帧格式]] —— CRC/ACK/EOF 错误源
- [[05-CAN仲裁与优先级]] —— 仲裁错乱触发错误
- [[03-CAN位定时与同步]] —— 位定时错导致 CRC 错
- [[10-CAN错误恢复与总线关闭]] —— 恢复深入
- [[14-CAN排查手册与速查表]] —— 错误速查
- [[10-SPI错误处理与恢复]] —— 对比 SPI 错误处理
- [[10-I2C错误处理与恢复]] —— 对比 I2C 错误处理
参考资料
- Bosch CAN Specification 2.0(错误处理章节)
- ISO 11898-1(错误管理)
- STM32 RM0090(CAN ESR/错误中断)
- ISO 26262 功能安全(CAN 容错)
[[00-CAN技术系列总目录]] · 上一篇:[[05-CAN仲裁与优先级]] ·下一篇:[[07-CAN高层协议]]
✨ 感谢你的阅读 ✨
技术之路漫漫,分享是为了更好地交流。
如果本文的内容对你有启发,希望能得到你的支持:
👍 点赞|⭐ 收藏|👀 关注
如果你在调试过程中遇到了其他问题,
欢迎在评论区 💬留言,我们一起探讨。
关注我,一起交流底层开发的那些事儿!🚀