串口日志染色与帧解析
一屏黑白日志看不清重点?按级别和时间戳着色,再把里面的 Modbus 报文和 CAN 帧捡出来,校验和周期一起列。
染色
最多分析 5000 行、显示前 300 行;Modbus RTU 必须通过 CRC 校验才算帧,CAN 支持 candump 的两种常见格式。
帧解析
按行号对应左侧日志,方便回头查上下文。
| 行 | 类型 | 地址 / ID | 摘要 | 校验 |
|---|---|---|---|---|
| 3 | Modbus RTU | 从站 1 | 读保持寄存器 起始 0,数量 10(从站 1) | CRC 通过 |
| 4 | Modbus RTU | 从站 1 | 读保持寄存器 响应 10 个寄存器(从站 1) | CRC 通过 |
| 6 | Modbus RTU | 从站 1 | 写单个寄存器 地址 1 ← 100(从站 1) | CRC 通过 |
| 7 | Modbus RTU | 从站 1 | 写单个寄存器 地址 1 ← 100(从站 1) | CRC 通过 |
| 10 | Modbus ASCII | 从站 1 | 读保持寄存器 起始 0,数量 10(从站 1) · ASCII | LRC 通过 |
| 12 | CAN | 0x123 | ID 0x123 · 8 字节 · 11 22 33 44 55 66 77 88 | 解析 |
| 13 | CAN | 0x7DF | ID 0x7DF · 8 字节 · 02 01 05 00 00 00 00 00 · OBD 诊断请求 | 解析 |
| 14 | CAN | 0x123 | ID 0x123 · 8 字节 · 11 22 33 44 55 66 77 88 | 解析 |
| 15 | CAN | 0x7E8 | ID 0x7E8 · 8 字节 · 03 41 01 0C 00 00 00 00 · OBD 诊断响应 | 解析 |
| 16 | CAN | 0x123 | ID 0x123 · 8 字节 · 11 22 33 44 55 66 77 89 | 解析 |
| 17 | CAN | 0x7DF | ID 0x7DF · 8 字节 · 02 01 05 00 00 00 00 00 · OBD 诊断请求 | 解析 |
| 19 | CAN 扩展 | 0x20000004 | ID 0x20000004 · 错误/过载帧 | 解析 |
CAN ID 统计
| ID | 帧数 | 平均周期 | 频率 | 数据变化 | 最后数据 |
|---|---|---|---|---|---|
| 0x123 | 3 | 20 ms | 50 Hz | 1 | 11 22 33 44 55 66 77 89 |
| 0x7DF | 2 | 50 ms | 20 Hz | 0 | 02 01 05 00 00 00 00 00 |
| 0x7E8 | 1 | — | — | 0 | 03 41 01 0C 00 00 00 00 |
| 0x20000004 | 1 | — | — | 0 | 00 00 00 00 00 00 00 00 |
按 500 kbps 估算,这段日志的 CAN 总线负载约 3%(892 位 / 0.06 秒)。 周期由相邻时间戳差的中位数得到;没有时间戳时只统计帧数和数据变化。
染色预览
文本保持原样,复制出去不带颜色标记。
1[] INFO boot serial monitor v1.4 2[] INFO UART0 115200 8N1, RX buffer 256 3[] TX: 01 03 00 00 00 0A C5 CD 4[] RX: 01 03 14 00 01 00 02 00 64 00 C8 01 2C 01 90 01 F4 02 58 02 BC 03 20 44 51 5[] INFO 10 registers updated 6[] TX: 01 06 00 01 00 64 D9 E1 7[] RX: 01 06 00 01 00 64 D9 E1 8[] ERROR CRC mismatch on slave 2, retry 1 9[] TX: 01 83 02 C0 F1 10:01030000000AF2 11 12(1700000000.000000) can0 123#1122334455667788 13(1700000000.010000) can0 7DF#0201050000000000 14(1700000000.020000) can0 123#1122334455667788 15(1700000000.030000) can0 7E8#0341010C00000000 16(1700000000.040000) can0 123#1122334455667789 17(1700000000.060000) can0 7DF#0201050000000000 18 19 can0 20000004 [8] 00 00 00 00 00 00 00 00
共 19 行符合条件,显示前 19 行。
日志里先看什么
串口日志最有价值的是「异常前后的上下文」,不是某一行本身。先按 ERROR、WARN 过滤,找到第一条异常,再往前看二三十行,通常能看到它是因为哪条命令、哪个返回值触发的。染色把时间戳、级别和十六进制分开,就是为了让这个来回翻的过程快一点。
Modbus 调试先确认三件事:从站地址对不对、功能码和寄存器范围对不对、CRC 有没有通过。CRC 不通过通常是线序接反、波特率不匹配、帧被截断,或者 RS-485 的 A/B 接反。工具把 CRC 不通过的候选单独计数,就是提醒你「这里有报文,但没解对」。
CAN 调试先看 ID 集合和周期。正常的总线上,每个 ID 的周期应该稳定,抖动通常来自总线负载过高、节点发送排队或者终端电阻不匹配。某个 ID 突然停止、数据变化次数异常少、DLC 和预期不符,都是排查方向。总线两端各 120Ω 终端电阻不能少,也不能多。
日志本身也会骗人。时间戳可能来自上位机而不是设备,缓冲区溢出会丢行,USB 转串口在高压差下会丢字节。怀疑丢数据时,先降波特率、换短线和带屏蔽的线,再回来分析协议。能稳定复现的日志,比一次“看起来很奇怪”的日志更有用。
需要单独核对报文格式,用Modbus 报文解析;串口波特率误差和采样点计算在串口波特率误差;CRC 参数速查在CRC 校验。
常见问题
为什么有些十六进制串没有被识别成 Modbus?
Modbus RTU 必须有合法的 CRC16。日志里的随机十六进制、截断的报文、少了最后两个字节的串都过不了校验,工具宁可不当成帧,也不愿给出一份假解析。确认帧完整、字节数对得上再试。
CAN 的两种格式都支持吗?
支持 candump 的两种常见输出:带通道名和方括号的 `can0 123 [8] 11 22 …`,以及紧凑的 `123#1122334455667788`。行首带 `(时间戳)` 的也能识别,时间戳用来算每个 ID 的周期和总线负载。
Modbus ASCII 和 RTU 怎么区分?
ASCII 帧以冒号开头,内容全是可打印十六进制字符,末尾是 LRC 校验;RTU 是二进制字节流,末尾是两字节 CRC16(低字节在前)。两种帧的从站地址、功能码和寄存器布局是一样的,只是传输编码不同。
功能码后面的寄存器值怎么读?
默认按无符号 16 位大端解释,和 Modbus 规范一致。温度、电流这类量常常带符号或需要乘系数(比如值 ÷ 10),工具给出原始值,换算要按设备手册来。32 位量通常占两个寄存器,高低字顺序各家不同。
CAN 周期统计为什么有的 ID 没有数值?
周期要靠时间戳算。candump 默认输出不带时间戳,需要加 `-ta`(绝对时间)或 `-L`(带日志时间)再导出。没有时间戳时仍能统计帧数、DLC 和数据变化次数,只是算不出间隔。
日志太长会不会卡?
页面最多分析五千行、显示三百行,超出的部分会截断。要分析完整日志,建议先用 `grep` 或时间范围筛出相关片段,再粘进来;或者导出 CSV 后在表格软件里做统计。