CAN调试 核心功能:抓包、发送、统计与解析
三、核心功能:抓包、发送、统计与解析
Linux 下的 SocketCAN 工具集是调试 CAN 最完整的一套命令行工具,覆盖了从抓包到回放的全过程。
| 工具 | 功能 | 典型用法 |
|---|---|---|
candump | 监听并打印总线报文 | candump can0 或按 ID 过滤 |
cansend | 发送单帧报文 | cansend can0 123#DEADBEEF |
cangen | 生成随机或指定模式的流量 | 压力测试总线负载 |
canplayer | 回放记录文件 | 离线复现现场问题 |
cansniffer | 只显示发生变化的数据字节 | 快速找出哪个字节在动 |
canbusload | 统计总线负载率 | 评估是否需要升级到 CAN FD |
canfdtest | CAN FD 链路测试 | 验证 FD 收发是否正常 |
ip 工具 | 接口配置与错误统计 | ip -details -statistics link show can0 |
报文格式是必须记牢的:candump 的输出形如 can0 123 [8] 11 22 33 44 55 66 77 88,依次是接口名、报文 ID、数据长度、八个数据字节。cansend 的写法是 can0 123#1122334455667788,# 前是 ID,后面是数据。# 后可以跟 R 表示远程帧,扩展帧则用 8 位十六进制 ID。
Python 侧用 python-can 可以写更灵活的分析脚本,适合做自动化测试与长时统计:
import can, time
bus = can.interface.Bus(channel="can0", bustype="socketcan")
# 周期发送
msg = can.Message(arbitration_id=0x123, data=[0x11, 0x22, 0x33, 0x44],
is_extended_id=False)
task = bus.send_periodic(msg, 0.01) # 10 ms 周期
time.sleep(5)
task.stop()
# 接收并按 ID 统计周期
t0 = {}
for frame in bus:
now = time.time()
if frame.arbitration_id in t0:
print(hex(frame.arbitration_id),
"period = %.1f ms" % ((now - t0[frame.arbitration_id]) * 1000))
t0[frame.arbitration_id] = now
上层协议的解析是理解报文的关键。原始报文只有 ID 和一堆字节,含义要靠协议定义。CANopen 里,NMT 用于管理节点状态,SDO 用于读写对象字典(配置参数),PDO 用于高速传输过程数据(实时控制量),心跳报文用于节点在线监测。解析 CANopen 需要一份 EDS 文件,里面定义了对象字典的索引、子索引与数据类型。J1939 主要用于商用车,ID 里编码了优先级、PGN、源地址,需要用 PGN 定义表来解析。自定义协议则应当维护一份 DBC 文件,把每个信号的起始位、长度、字节序、缩放因子与偏移量写清楚,用 DBC 解析比人工数位可靠得多。
关于字节序,这是解析时最容易出错的地方。同一个多字节信号,如果发送方按小端排列而解析方按大端读,得到的是一个完全错误但看起来"像那么回事"的数值。排查方法是让设备输出一个已知值(比如把某个量设为 1.0 或 100),观察原始字节,反推排列方式,不要凭直觉假定。

