Wireshark CANopen 协议分析
目录
Wireshark 是功能强大的网络协议分析工具,配合 CANopen 解码插件,可以直观地分析 CANopen 通信流程。
1. Wireshark 安装与配置
1.1 安装 Wireshark
# Ubuntu/Debian
sudo apt-get install wireshark
# Fedora
sudo dnf install wireshark
# macOS
brew install --cask wireshark1.2 安装 CANopen 解码插件
Wireshark 默认支持 CAN 帧解析,但需要额外插件才能完整解码 CANopen 协议。
# 从源码安装 CANopen Wireshark 插件
git clone https://github.com/linnemann77/wireshark-canopen-plugin.git
cd wireshark-canopen-plugin
mkdir build && cd build
cmake ..
make
sudo make install
# 或者使用预编译版本(某些发行版)
sudo apt-get install wireshark-canopen1.3 配置 CAN 接口
物理 CAN 接口
# 创建虚拟 CAN(用于测试)
sudo modprobe vcan
sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0
# 配置 SocketCAN 为非阻塞模式
sudo ip link set vcan0 mtu 72在 Wireshark 中选择接口
- 启动 Wireshark
- 在捕获界面中选择
vcan0接口 - 点击右上角的齿轮图标配置过滤器
2. Wireshark 基础操作
2.1 开始捕获
┌─────────────────────────────────────────┐
│ Wireshark 捕获界面 │
├─────────────────────────────────────────┤
│ [☑] vcan0 [蓝色鲨鱼] [▼] │ ← 选择接口
│ │
│ [捕获过滤器] can │ ← 输入过滤器
│ │
│ [▶ 开始捕获] [⚙ 设置] │
└─────────────────────────────────────────┘2.2 捕获过滤器
# 捕获所有 CAN 帧
can
# 只捕获特定 ID 范围
can.id == 0x123
# 捕获 CANopen NMT 消息
can.id == 0x000
# 只捕获节点 2 的消息
can.id >= 0x200 && can.id <= 0x27F2.3 显示过滤器
# 显示所有 SDO 消息
can.opcode == 0x600 || can.opcode == 0x580
# 显示节点 2 的所有通信
can.node == 2
# 显示错误帧
can.flags.error == 1
# 显示心警报
can.opcode == 0x700 && can.data[0] == 0x803. CANopen 协议解析
3.1 NMT 协议分析
消息结构
CAN ID: 0x000
Data: [Command][Node ID]Wireshark 显示示例
Frame 1: 8 bytes on wire (64 bits), 8 bytes captured (64 bits) on interface vcan0
CAN
Identifier: 0x000
Flags: Standard
Data: 0102
CANopen
Message Type: NMT Command
NMT Command: Start Remote Node (0x01)
Node ID: 2常见 NMT 命令
| 命令值 | 名称 | 功能 |
|---|---|---|
| 0x01 | Start Remote Node | 启动远程节点 |
| 0x02 | Stop Remote Node | 停止远程节点 |
| 0x80 | Enter Pre-Operational | 进入预运行状态 |
| 0x81 | Reset Node | 节点复位 |
| 0x82 | Reset Communication | 通信复位 |
3.2 SDO 协议分析
SDO 请求帧(Client → Server)
CAN ID: 0x600 + Node ID
Data: [CCS][n][e][s][IndexHigh][IndexLow][SubIndex][Data...]SDO 响应帧(Server → Client)
CAN ID: 0x580 + Node ID
Data: [SCS][n][e][s][IndexHigh][IndexLow][SubIndex][Data...]Expedited 传输示例
Frame 10: 8 bytes on wire
CANopen
Message Type: SDO Request
Direction: Client -> Server
Command Specifier: 0x23 (Initiate Download)
Node ID: 2
Expedited Transfer: Yes
Size Indicated: Yes
Data Size: 4 bytes
Index: 0x1000 (Device Type)
Sub-Index: 0x01
Data: 0x12345678Segmented 传输示例
Frame 20: SDO Request - Initiate Download
Command Specifier: 0x21 (Initiate Download)
Segmented Transfer: Yes
Size Indicated: Yes
Total Size: 64 bytes
Index: 0x2000
Sub-Index: 0x00
Frame 21: SDO Response - Initiate Download Response
Command Specifier: 0x60 (Upload Segment Response)
Toggle Bit: 0
Frame 22: SDO Request - Download Segment
Command Specifier: 0x00 (Download Segment)
Data: [7 bytes]
Frame 23: SDO Response - Download Segment Response
Command Specifier: 0x20 (Download Segment Response)
Toggle Bit: 1
... (重复直到完成)SDO Abort 示例
Frame 100: SDO Response - Abort
Command Specifier: 0x80 (Abort)
Abort Code: 0x06020000 (Object does not exist)
Index: 0x1234
Sub-Index: 0x003.3 PDO 协议分析
TPDO (Transmit PDO)
Frame 50: TPDO
CANopen
Message Type: TPDO
Node ID: 2
PDO Number: 1
COB-ID: 0x180 + 0x002 = 0x182
Data:
[0] Mapping 1: 0x1234 (Value)
[1] Mapping 2: 0x5678 (Value)
[2] Mapping 3: 0x9ABC (Value)
[3] Mapping 4: 0xDEF0 (Value)RPDO (Receive PDO)
Frame 60: RPDO
CANopen
Message Type: RPDO
Node ID: 2
PDO Number: 1
COB-ID: 0x200 + 0x002 = 0x2023.4 心跳协议分析
Frame 30: Heartbeat
CANopen
Message Type: Heartbeat
Node ID: 2
State: Operational (0x05)心跳状态值
| 值 | 状态 | 说明 |
|---|---|---|
| 0x00 | Boot-up | 节点正在启动 |
| 0x04 | Stopped | 已停止 |
| 0x05 | Operational | 运行中 |
| 0x7F | Pre-Operational | 预运行状态 |
4. 高级分析技巧
4.1 统计功能
IO 图表
菜单: Statistics -> I/O Graph
用途: 可视化总线负载和消息频率
X 轴: 时间
Y 轴: 每秒帧数/字节数
配置示例:
- Graph 1: all packets, Packets/s, 蓝色
- Graph 2: can.opcode == 0x700, Packets/s, 绿色(心跳)
- Graph 3: can.opcode == 0x600 || 0x580, Packets/s, 红色(SDO)对话统计
菜单: Statistics -> Conversations -> CAN
用途: 查看节点间通信统计
输出:
- 节点对 (Node A -> Node B)
- 交换的消息数
- 数据量
- 最小/最大/平均间隔协议层级统计
菜单: Statistics -> Protocol Hierarchy
用途: 查看各协议消息分布
输出:
CANopen
├── NMT Command (5 packets, 0.5%)
├── Heartbeat (100 packets, 10%)
├── SDO (200 packets, 20%)
└── PDO (700 packets, 70%)4.2 流跟踪
TCP 风格的会话跟踪
右键点击消息 -> Follow -> CANopen Stream
用途:
- 跟踪完整的 SDO 会话
- 查看 Request/Response 配对
- 分析时序关系
输出:
Frame 10: SDO Request (Read 0x1000:00)
Frame 11: SDO Response (Value: 0x00000192)
Time delta: 0.5ms4.3 时间分析
消息间隔分析
# 计算特定消息的间隔时间
# 方法 1: 在 Wireshark 中
View -> Time Display Format -> Seconds since previous displayed packet
# 方法 2: 导出后分析
File -> Export Packet Dissections -> As JSON...时序关系图
菜单: Statistics -> Flow Graph
类型: TCP Flow
显示:
- NMT Start -> Bootup -> Heartbeat 序列
- SDO Request -> SDO Response 时序
- PDO 发送频率5. EDS 文件集成
5.1 什么是 EDS 文件?
EDS (Electronic Data Sheet) 文件描述了 CANopen 节点的对象字典结构,是理解 CANopen 通信的关键。
5.2 加载 EDS 文件
菜单: Edit -> Preferences -> Protocols -> CANopen
1. 添加 EDS 文件目录
2. 指定 EDS 文件位置
3. 映射节点 ID 到 EDS 文件5.3 示例 EDS 映射
[1018]
ParameterName=Identity Object
ObjectType=0x8
DataType=0x0007
AccessType=rw
DefaultValue=0x00000000
PDOMapping=0
[1018sub0]
ParameterName=Number of Entries
ObjectType=0x7
DataType=0x0005
AccessType=rw
DefaultValue=4加载后,Wireshark 会自动解析对象索引/子索引的含义。
6. 常见场景分析
6.1 分析 SDO 超时
问题: SDO 请求后无响应
分析步骤:
1. 查找 SDO Request 帧
2. 使用显示过滤器: can.opcode == 0x600
3. 查看后续是否有 SDO Response
4. 检查时间差是否超过超时时间
5. 查看是否有其他错误帧
# 查找超时的 SDO 请求
can.opcode == 0x600 && !frame.time_delta > 1.06.2 分析 PDO 更新频率
问题: PDO 更新不规律
分析步骤:
1. 过滤特定 TPDO: can.id == 0x182
2. 右键 -> Apply as Filter -> Selected
3. Statistics -> I/O Graph
4. 设置时间窗口为 1 秒
5. 观察波动模式6.3 分析 NMT 状态转换
问题: 节点无法进入 Operational 状态
分析步骤:
1. 查找 NMT 命令: can.id == 0x000
2. 查找 Bootup 消息: can.id == 0x700 && can.data[0] == 0x00
3. 查找心跳消息: can.id == 0x7XX
4. 使用 Flow Graph 查看转换序列
# 正常序列
NMT Start -> Bootup -> Pre-Operational Heartbeat -> Operational Heartbeat6.4 分析总线错误
问题: 频繁错误帧
分析步骤:
1. 查找错误帧: can.flags.error == 1
2. 查看错误统计: Statistics -> CAN Bus Errors
3. 分析错误类型:
- Error Active: 节点主动报错
- Error Passive: 节点被动状态
- Bus Off: 总线关闭
# 查找变为 Bus Off 的帧
can.flags.error == 1 && can.data[0] == 0x007. 自动化分析脚本
7.1 使用 TShark(命令行)
# 统计各类型消息数量
tshark -r capture.pcap -T fields -e can.opcode | sort | uniq -c
# 导出 SDO 会话
tshark -r capture.pcap -Y "can.opcode == 0x600 || can.opcode == 0x580" \
-T fields -e frame.number -e can.id -e can.data
# 查找超时的 SDO 请求
tshark -r capture.pcap -Y "can.opcode == 0x600" \
-T fields -e frame.number -e can.id | \
while read num id; do
next=$((num + 10))
if ! tshark -r capture.pcap -Y "frame.number > $num && frame.number < $next && can.opcode == 0x580" | grep -q .; then
echo "Frame $num (ID=$id): No SDO response"
fi
done7.2 Python 脚本分析
#!/usr/bin/env python3
# analyze_canopen.py - CANopen 日志分析
import pyshark
import sys
def analyze_sdo_sessions(cap):
sdo_sessions = []
current_session = None
for packet in cap:
if 'CANopen' in packet:
if packet.can.opcode == '0x600': # SDO Request
if current_session:
sdo_sessions.append(current_session)
current_session = {
'request_frame': int(packet.frame_info.number),
'request_id': packet.can.id,
'request_index': packet.canopen.index,
'request_subindex': packet.canopen.subindex,
}
elif packet.can.opcode == '0x580' and current_session: # SDO Response
current_session['response_frame'] = int(packet.frame_info.number)
current_session['response_id'] = packet.can.id
current_session['latency_ms'] = float(packet.frame_info.time_delta) * 1000
sdo_sessions.append(current_session)
current_session = None
return sdo_sessions
def find_timeouts(sessions, timeout_ms=100):
timeouts = [s for s in sessions if 'response_frame' not in s or s.get('latency_ms', 0) > timeout_ms]
return timeouts
if __name__ == '__main__':
cap = pyshark.FileCapture(sys.argv[1])
sessions = analyze_sdo_sessions(cap)
timeouts = find_timeouts(sessions)
print(f"Total SDO sessions: {len(sessions)}")
print(f"Timeouts: {len(timeouts)}")
for t in timeouts[:5]: # 显示前 5 个
print(f"Frame {t['request_frame']}: No response (ID={t['request_id']})")★ Insight ─────────────────────────────────────
- Wireshark 的 IO Graph 是诊断总线负载问题的利器——正常 CANopen 总线负载应 < 80%,持续超过 90% 说明有严重问题。
- SDO 会话跟踪功能可以快速定位超时原因:有时候不是没有响应,而是响应被丢弃或 ID 错误。
- 加载 EDS 文件后,原始的 16 进制数据会被翻译成有意义的参数名,这是理解 CANopen 协议的关键步骤。
─────────────────────────────────────────────────
下一步
→ 04-log-analysis.md —— 日志分析与自动化
如果这篇文章对你有帮助,欢迎请我喝杯咖啡 ☕
支付宝
微信