# CAN 非阻塞发送改造 · 隐患记录 > 记录时间:2026-08-29 > 背景:修复“拔掉 CAN1 后,CAN2 上的 pitch / 摩擦轮 / 拨盘电机明显抖动”的问题。 ## 一、本次改动摘要 | 文件 | 改动 | 目的 | | --- | --- | --- | | bsp/can/bsp_can.c | `CANTransmit()` 由忙等改为非阻塞 | 避免某一路 CAN 离线时拖慢电机控制任务 | | bsp/can/bsp_can.c | `CANAddFilter()` 对 `can_filter_conf` 先 `memset` 清零 | 避免未初始化字段成为垃圾匹配 ID | | Src/can.c | CAN1/CAN2 的 `AutoBusOff` 改为 `ENABLE` | 断开后重新连接能自动从 bus-off 恢复 | ## 二、隐患与风险 ### 1. 双板模式下的 `CANCommSend` 多帧发送可能丢包(当前为休眠隐患) - 相关位置:`modules/can_comm/can_comm.c` 的 `CANCommSend()`(约 106、116、121 行)。 - `CANCommSend()` 按每 8 字节一帧连续发送。当待发送数据超过 24 字节(即超过 3 帧)时,第 4 帧起会因为 3 个发送邮箱都还在忙碌而被直接丢弃。 - 原来的忙等版本会等待邮箱空闲后继续发完,非阻塞版本不会。 - 当前工程为 `ONE_BOARD`,该路径未参与编译,暂无影响;一旦切换到 `CHASSIS_BOARD` / `GIMBAL_BOARD`,此问题会暴露。 ### 2. 丢帧变为静默,失去诊断信息 - 相关位置:`bsp/can/bsp_can.c` 的 `CANTransmit()`(约 107 行)。 - 原实现邮箱满时会打印 `LOGWARNING`;现在直接 `return 0`,不重试、不记录。 - 未来若总线设备增多或发送频率升高出现真实拥塞,丢帧将不可见,排查难度增加。 - 对 DJI 电机本身影响较小:500 Hz 控制帧偶尔丢一两帧,电机内部看门狗时间远大于 2 ms,不会触发保护。 ### 3. `timeout` 参数实际失效 - `CANTransmit()` 签名仍保留 `float timeout`,但函数内部用 `(void)timeout` 忽略了它。 - 调用方传入的 `1`、`0.2`、`0.5` 等值已不再生效,存在可读性与预期一致性隐患。 ### 4. `AutoBusOff` 行为变化 + CubeMX 覆盖风险 - 相关位置:`Src/can.c`(约 48、80 行)。 - 改为 `ENABLE` 后,持续总线故障(如短路)会导致控制器在 bus-off ↔ 恢复之间反复循环;当前未开启 CAN 错误中断,不会产生中断风暴,但行为不同于 `DISABLE` 时的锁死状态。 - `Src/can.c` 是 CubeMX 生成文件,从 `basic_framework.ioc` 重新生成工程时会被覆盖回 `DISABLE`,需要同步修改 `.ioc` 中的 Automatic Bus-Off Management 选项。 ### 5. 过滤器配置 `memset`(基本无风险) - 相关位置:`bsp/can/bsp_can.c` 的 `CANAddFilter()`(约 32 行)。 - 属于纯修正,无副作用。 ## 三、建议后续动作 - [ ] 若将来启用双板,给 `CANCommSend()` 的多帧发送增加“短且有界”的等待/重试,避免丢中间帧。 - [ ] 评估是否为 `CANTransmit()` 增加可选的丢帧统计或低频告警,在“不阻塞任务”与“可诊断”之间取得平衡。 - [ ] 在 `basic_framework.ioc` 中同步开启两个 CAN 的 Automatic Bus-Off Management,避免重新生成代码时被覆盖。 ## 四、相关文件 - `bsp/can/bsp_can.c` - `modules/can_comm/can_comm.c` - `Src/can.c`