CAN 数据丢帧?别只加 FIFO,看看接收过载与错误处理
摘要CAN 总线波形正常但上位机偶尔收不到某一帧数据或者节点突然进入“被动错误”状态不是波特率问题而是接收 FIFO 溢出或错误计数器触发的自我保护。本文解析 CAN 的“隐身杀手”——错误帧。一、问题描述现象**CAN 总线负载率只有 30%理论上不会丢包但监控软件偶尔抓不到报文或者某个节点突然“失联”示波器看总线还在跳但它就是不回 ACK。**很多工程师的排查方向是FIFO 深度不够中断里处理太慢换个更强的 MCU二、原理分析1. 物理模型CAN 控制器有一套自治的错误处理机制。接收报文 - [Acceptance Filter] - [FIFO] - [CPU Interrupt]2. 核心参数FIFO 深度通常只有 3 级STM32。Error Counter错误计数器TEC / REC。State节点状态Active - Passive - Bus Off。3. 反直觉真相CAN 丢帧通常不是“没收到”而是“被硬件丢弃了”。FIFO 溢出中断处理慢了一点点第 4 帧进来硬件直接丢弃且不通知你。错误被动Error Passive节点发送错误过多被禁止主动发送只能被动接收。Bus Off节点自我隔离彻底沉默。三、工程级解决方案方案 1必须处理 FIFO 溢出软件解法不要指望 FIFO 无限缓存。// 在 CAN 中断里 if (__HAL_CAN_GET_FLAG(hcan, CAN_FLAG_FOV0)) { __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FOV0); // 记录一次溢出错误 can_fifo_overflow_cnt; }最佳实践中断里只做标记不做复杂处理。在任务线程中处理 CAN 数据。方案 2监控错误计数器救命稻草在调试阶段把错误计数器读出来。uint8_t rec (hcan.Instance-ESR 24) 0xFF; // REC uint8_t tec (hcan.Instance-ESR 16) 0xFF; // TEC判读标准REC/TEC 96 → 进入 Error Passive。TEC 255 → Bus Off。方案 3Bus Off 自动恢复量产必加默认情况下Bus Off 后需要手动复位。自动恢复流程检测到 Bus Off 标志。等待 128 次连续 11 个隐性位。重新初始化 CAN 外设HAL_CAN_Init。四、选型避坑建议不要屏蔽错误中断ERROR 中断是 CAN 的“黑匣子”必须开启。验收滤波器Filter列表模式List适合节点少、ID 固定的场景。掩码模式Mask适合批量 ID 过滤。不要过度降噪有些工程师为了“稳”把所有错误帧都屏蔽结果总线真正出问题时你完全不知道。五、总结 Checklist[ ] 是否开启了 CAN ERROR 中断[ ] FIFO 溢出时是否有计数或日志[ ] Bus Off 后是否有自动恢复机制[ ] 验收滤波器是否配置正确没把 ID 过滤掉六、写在最后关注我少走弯路我是 gqqsherry一个拒绝调包、专注底层逻辑的嵌入式工程师。CAN 的错误处理机制是“最不像单片机外设”的部分它更像一个微型操作系统。关注我的专栏《嵌入式底层避坑指南》我会持续更新 CAN、UART、SPI 等外设的真实调试案例和量产级解决方案。下一篇预告《CAN FD 跑不起来别只怪线缆看看采样点与位时序》ReferencesISO 11898-1 – CAN error handling and fault confinementSTM32 Reference Manual – CAN error status register如果你在项目中遇到过 CAN 节点“假死”或 Bus Off 问题欢迎在评论区分享你的排查经验。原创文章转载请注明出处。