跳到主要内容

排错专题:CAN 错误计数与 Bus-Off

当程序显示 TWAI 初始化成功,但收不到电机响应时,先不要改 SDO 对象地址。CAN 控制器的错误状态能帮助判断问题还在物理总线,还是已经进入 CANopen 层。

先看三个现象

现象首先怀疑
一帧都收不到,发送错误持续增加电机未供电、CANH/CANL、位速率、终端
能收到 0x701,但某个 SDO 返回 AbortCAN 已通,转查对象和权限
曾能通信,随后进入 Bus-Off总线持续错误、接线松动、位速率异常或严重干扰

TEC 和 REC 是什么

CAN 控制器内部维护错误计数:

计数英文主要反映
TECTransmit Error Counter本节点发送时遇到的错误
RECReceive Error Counter本节点接收时遇到的错误

计数不是简单的“错误总次数”。CAN 规则会按错误类型增加或减少它们,并据此改变节点错误状态。

从正常错误状态到 Bus-Off

三种关键状态

状态可以怎样理解
Error Active正常通信,发现错误时主动通知总线
Error Passive错误计数已经较高,控制器限制自己的错误影响
Bus-Off发送错误严重,控制器退出总线发送

Bus-Off 不是 CANopen 状态,也不是电机的 CiA 402 Fault。它发生在 CAN 控制器层。

ACK 能证明什么

一帧发送时,总线上至少另一个正常接收节点会在 ACK 槽给出确认。如果没有任何节点 ACK,发送端会认为本次发送失败并重试,TEC 往往继续增加。

因此:

  • TX 成功可以证明总线上有节点正确接收到了 CAN 帧并给出 ACK;
  • ACK 不能证明电机应用接受了命令;
  • SDO 下载成功还需要看到电机的 0x581 成功响应;
  • 电机实际执行还要再读状态和反馈。

按顺序检查,不要同时改五项

  1. 给电机和底板断电。
  2. 测量 CANH 与 CANL 之间电阻,双端 120 Ω 时应接近 60 Ω。
  3. 核对 CANH 对 CANH、CANL 对 CANL,不能互换。
  4. 核对电机和控制板共地。
  5. 重新供电,确认电机 LED 有正常状态。
  6. 确认两端均使用 500 kbit/s Classical CAN。
  7. 只运行接收实验,观察是否出现 0x701
  8. 接收正常后再运行 SDO 实验。

如果第 7 步能稳定收到 0x701,就不应继续把主要精力放在终端电阻或 TX/RX 引脚上。

TX 和 RX 引脚别与 CANH/CANL 混淆

本实验信号路径是:

芯片侧收发器侧总线侧
ESP32 GPIO19TJA1050 TXDCANH/CANL
ESP32 GPIO18TJA1050 RXDCANH/CANL

GPIO19/18 是 3.3 V 数字信号;CANH/CANL 是差分总线信号。不能把 ESP32 GPIO 直接接电机 CANH/CANL。

Bus-Off 恢复不是快速重启循环

进入 Bus-Off 后,应用可以发起恢复,但必须让控制器和总线满足 CAN 规定的恢复条件。正确思路是:

  1. 记录 Bus-Off 时间和错误计数;
  2. 停止继续提交 CANopen 请求;
  3. 等待一段受控时间,不在日志循环中不停重启;
  4. 调用当前 ESP-IDF 驱动提供的恢复流程;
  5. 确认恢复完成后,再逐步恢复通信;
  6. 如果短时间再次 Bus-Off,停止自动尝试并检查硬件。

无限快速重启会刷屏、增加总线干扰,还会掩盖真正的接线或位速率问题。

ESP-IDF v5.5.4 TWAI 官方文档:Two-Wire Automotive Interface

记录故障时保存什么

不要只发最后一句 Bus-Off。保存:

  • 首次错误前后至少 5 秒日志;
  • TEC、REC 和总线错误计数;
  • TX 成功、TX 失败、仲裁丢失、Error Passive、Bus-Off 的时间顺序;
  • 当时运行的工程和命令;
  • 电机 LED、供电电压和 CANH/CANL 断电电阻;
  • 是否能收到任何其他节点的 Heartbeat。

这些信息足以把“完全没有物理通信”和“通信后协议被拒绝”分开。