协议分析

协议解码视图

看帧,不看字节:校验一目了然,请求与响应自动配对,寄存器按手册的编号显示。

本页内容

协议解码视图

协议解码视图把一个连接的收发数据列成一张帧表:每个请求、响应或残缺的片段占一行,校验已经算好,请求与响应自动配对,每个字段逐项解释。Modbus RTU、Modbus ASCII 和 Modbus TCP 直接就能解;私有的二进制协议,用帧模板描述一遍之后也能解(Free 版对解码帧数和可用模板有限制,见文末)。

每个连接有自己的面板,位于它的接收区下方。打开方式:

  • 视图 → 协议解码面板 显示或隐藏当前连接的面板;
  • 或者在接收区右键,勾选协议解码。

然后在面板左上角选一个解码器。接收区本身不受任何影响,解码器是在旁边读同一份字节。收发两个方向都解码:连接发出的(TX)和收到的(RX)各走各的数据流,你发的请求和设备的回复不会互相搅乱对方的帧。TCP Server 或 UDP 连接下,每个客户端分开解码,表里会多出对端一列。

面板默认隐藏,隐藏时不做任何解码:面板关着时到达的字节,之后也不会补解,所以要先打开面板,再抓想看的数据。文件传输的字节永远不解码。每个连接选的解码器、面板是否显示,都随工程保存。

主窗口中的 TCP 连接,接收区以 Hex 显示。下方是协议解码面板,解码器为 Modbus RTU,共 20 帧:帧表里是从站 1 的发送请求与接收响应,除一行异常外状态都是正常。选中了一条读响应,右侧字段树列出从站 1、功能码 0x03、字节数 6、寄存器 40001、40002、40003 及其数值、CRC 正常以及与之配对的帧,下方是这一帧的十六进制条
TCP 上的 Modbus RTU:每条响应都和它的请求配对,每个寄存器按 40001 式参考号命名。

面板怎么看

面板顶部一行依次是解码器下拉框、模板...(打开帧模板编辑器)、清空(清空帧表)、导出和自动滚动;右侧显示表中的帧数,✕ 用来隐藏面板。

帧表每帧一行:

列 内容
# 帧的序号;清空帧表或更换解码器后继续往下编号
时间 这一帧第一个字节所在的那次读取到达的时间,精确到毫秒
方向 TX 或 RX
对端 客户端地址,只在 TCP Server 和 UDP 连接下出现
长度 帧的字节数
摘要 一行概括:Modbus 是从站、功能码和地址范围;模板是前几个字段
状态 见下表
原始字节 开头几个字节;完整内容在悬停提示和十六进制条里
状态 含义
正常 完整,校验正确
异常(橙色) Modbus 异常响应,校验正确
校验错误(红色) 形状像一帧,但 CRC、LRC 或校验和不对
格式错误(红色) 校验正确或没有校验,但形状不对:长度对不上、帧尾不对
不完整(红色) 一帧收到一半时线路静默了,或连接关闭了
无法识别(灰色) 不属于任何帧的字节;每行最多 256 字节

选中一行,右侧(连接较窄时在帧表下方)显示它的字段,分字段、值、原始字节和帧内偏移四列,有错误的字段显示为红色。再选中某个字段,下方显示整帧的十六进制条里就会高亮这个字段对应的字节。

响应与请求配对后,选中其中一条,另一条在表里会被标上底色;字段里多出一行配对帧,给出对方的序号和以毫秒计的往返时间;双击这一行直接跳过去。在行上右键可以:

  • 转到配对帧;
  • 在接收区查找这些字节:跳到这一帧的字节在接收区最后出现的位置。需要接收区是 Hex 显示;被时间戳行拆开的帧找不到;
  • 复制十六进制:这一帧的字节;
  • 复制选中行(Ctrl+C)。

帧表保留最近的 5000 帧,右侧计数会注明丢弃了多少较早的帧。更换解码器、或编辑正在使用的模板,都会清空帧表,保证表里每一行都是当前解码器拆出来的;只改模板名称不会清空。连接 → 清除全部显示 会连同接收区一起清空帧表。

Modbus RTU、ASCII 与 TCP

按线上跑的是什么来选解码器,而不是按连接类型:

解码器 适用于
Modbus RTU 以 CRC-16 结尾的二进制帧,走 RS-485 / RS-232;以及经串口服务器转发的 RTU over TCP
Modbus ASCII 以十六进制文本书写、以 : 开头、CR LF 结尾、用 LRC 校验的帧
Modbus TCP 带 MBAP 头(事务号、协议号、长度、单元号)、没有 CRC 的帧,通常在 502 端口

串口服务器工作在「RTU over TCP」模式时,TCP 连接上跑的是 RTU 帧,应选 Modbus RTU。帧表里满是「无法识别」,通常说明解码器选错了。

功能码 01~06、07、08、0B、0C、0F、10、11、16、17、2B 都有名称,并逐字段解释:起始地址与数量、字节数(会和请求核对)、线圈的开/关,每个寄存器同时给出十六进制和十进制,最高位为 1 时再给出有符号值,如 0xFFFF (65535 / -1)。异常响应显示异常码和名称,例如 从站 1 · 异常 02 非法数据地址(读保持寄存器)。

一帧是请求还是响应,由它的形状决定;两种都说得通时(例如写单个寄存器的回显),有一条匹配且还在等回复的请求,它就算响应。方向不参与判断,所以无论 SPU 是主站、模拟从站,还是只在 RS-485 总线上旁听、两边的数据都从 RX 进来,都能正确解码。

响应与之配对的,是还在等回复的请求里最早的那条:从站号和功能码相同(Modbus TCP 还要求事务号相同)、来自同一个客户端、且发出不超过 2 秒——半双工总线本来就是按顺序应答的。串口线上的从站 0 是广播,没有人应答,所以不参与配对。

寄存器参考号与 PDU 地址

帧里的地址从 0 开始:第一个保持寄存器是 00 00。设备手册则多半沿用传统编号:从 1 开始,再在前面加一位表示是哪张表:

参考号 表 功能码
0xxxx 线圈 01、05、0F
1xxxx 离散输入 02
3xxxx 输入寄存器 04
4xxxx 保持寄存器 03、06、10、16、17

所以「40001」就是保持寄存器地址 0,「40108」是地址 107,线上写作 00 6B。超过 9999 时用六位写法:地址 9999 是 410000。

解码器两种都给出,免去「差一」的心算:起始地址显示为 0x006B = 107 (40108),请求的摘要是 40108-40110 (3),配对后的响应里每个寄存器单独一行、以参考号命名:40108、40109、40110。如果响应里的寄存器显示成 [0]、[1]……说明没有看到它的请求:请求发出时面板还没打开,或者回复晚于 2 秒。

设备不理请求、或回复「非法数据地址」时,先把起始地址按两种写法和手册对一遍:手册里的「1 号寄存器」可能是 40001(地址 0),也可能就是地址 1。手工拼帧时核对 CRC,见 CRC 与 Modbus 校验。

RTU 为什么不怕拆包合包

按规范,Modbus RTU 帧以 3.5 个字符时间的静默作为结束。这段静默到不了你的电脑:USB 转串口按自己的定时把字节成块交上来,串口服务器按自己的节奏打包成 TCP 报文,操作系统再随意合并或拆开读取。一帧可能分两次读到,轮询快的时候,请求和响应常常落在同一次读取里。

所以 SPU 不靠时序给 RTU 分帧,而是靠 CRC:在数据流开头,按功能码允许的几种长度逐一尝试,CRC 对得上的就是一帧;都对不上时,向后找下一个可能是帧头的位置(从站 0~247、已知功能码、长度放得下)且 CRC 对得上的地方,从那里接着解,跳过的字节成为一行「无法识别」。静默只用来处理拆不出来的部分:一帧收到一半后静默 100 毫秒,就显示为「不完整」。

结果是:不管字节经过 USB 转串口、RS-485 转换器还是 RTU over TCP,拆出来的帧都一样。Modbus ASCII 靠 : 和 CR LF 分帧,Modbus TCP 靠报文头里的长度分帧,同样不依赖时序。

用帧模板解私有协议

帧模板描述一种私有二进制协议:怎样在数据流里找到一帧、怎样校验、每个字段是什么意思。用 工具 → 帧模板... 或面板上的模板...按钮打开编辑器。左侧是模板列表,下面的按钮可以添加、复制、删除、上移、下移;每个模板的名称不能重复。点确定保存后,所有模板都会出现在面板的解码器下拉框里。

拆帧,即从数据流里切出帧的方式:

方式 一帧是
帧头 + 长度 先是帧头(十六进制),后面某处有一个长度字段:长度字段位于字节 N,宽度 1、2 或 4 字节,按某种字节序;计算的范围可选整帧、其后的字节或其后到校验之前的字节;修正取 −64~64,用于多计或少计一个字节的协议
帧头 + 固定长度 帧头之后总是同样的帧长
分隔符 直到分隔符(十六进制)为止的全部字节,如 0D 0A
空闲间隔 直到静默若干毫秒为止的全部字节

尽量用两种帧头方式:和上面的 RTU 一样,它们不依赖时序;而且一帧校验失败时不会马上放弃——如果它里面后面还有一个帧头、从那里开始是一帧校验正确的帧,就从那里接着解。空闲间隔只和你与设备之间的转换器一样可靠。帧尾(十六进制)可选,设了就会检查。最大帧长把一帧限制在 4~4096 字节,帧超时是半帧等多久之后显示为「不完整」。

校验:无、SUM8、XOR8、SUM16,或 CRC 计算器里的任意算法(包括 CRC-16/MODBUS),也可以选自定义 CRC,填宽度、多项式、初值、结果异或值和输入/输出反转。校验范围从你指定的字节开始,到校验之前为止;校验位于帧末尾、帧尾之前。SUM16 和 CRC 还要选存放顺序。

字段,每行一个:

列 内容
名称 显示在字段列表和摘要里
偏移 第一个字节的位置,从帧开头算起
类型 U8、I8、U16、I16、U32、I32、U64、I64、F32、F64、Hex、ASCII 或 Bits
长度 Hex 与 ASCII 是字节数(留空表示一直到校验之前);Bits 是容器大小,1、2 或 4 字节
位 Bits 字段占用的位,5..7 表示第 5 到第 7 位,第 0 位为最低位
字节序 大端(AB CD)、小端(DC BA)、字交换(CD AB) 或 字节交换(BA DC);后两种是 Modbus 设备存放 32 位数值常用的顺序
倍率、偏置、小数位、单位 显示值 = 原始值 × 倍率 + 偏置,按指定小数位显示并加上单位
取值标签 给取值起名字,如 0=关;1=开
条件 只在某字节为某值时显示这个字段:3=01 表示第 3 字节为 0x01;留空表示总是显示

底部的测试框用与连接上完全相同的解码器,解码你粘贴进去的十六进制字节,逐帧列出结果,选中一帧即显示它的字段。正式使用模板之前,先从接收区复制一段数据粘到这里试一试。

模板属于工程:随 .spu 保存,打开工程就恢复;没有打开工程时保存在本机。模板改名后,使用它的连接会跟着改;模板删除后,这些连接的解码器回到「关闭」。

帧模板对话框,打开的是模板「传感器 AA55」:方式为帧头 + 长度,帧头 AA 55,长度字段位于字节 2、宽度 1、计算其后到校验之前的字节,校验为 SUM8、从字节 2 开始;三个字段:命令,U8,偏移 3,取值标签 1=读数;2=校准;温度,I16,偏移 4,倍率 0.1,单位 °C;数值,F32,偏移 6。下方测试框粘贴了两帧并已解码,两帧都是正常,列出了第一帧的字段
下文示例的帧模板,先在测试框里验证,再用到连接上。

示例:一个传感器协议

假设某传感器的手册这样描述它的帧:

字节 内容
0–1 帧头 AA 55
2 长度:其后到校验之前的字节数
3 命令:1 = 读数,2 = 校准
4–5 温度,有符号,大端,单位 0.1 °C
6–9 数值,大端 32 位浮点
10 第 2 到第 9 字节的 SUM8

收到的一帧是 AA 55 07 01 01 02 41 20 00 00 6C。在 工具 → 帧模板... 里添加一个模板,依次填写:

  1. 名称 传感器 AA55;方式选帧头 + 长度;帧头(十六进制) AA 55;帧尾留空。
  2. 长度字段位于字节 2,宽度 1,计算选其后到校验之前的字节,修正 0。
  3. 校验选 SUM8,校验范围从字节 2 开始。
  4. 字段:命令,偏移 3,U8,取值标签 1=读数;2=校准;温度,偏移 4,I16,大端(AB CD),倍率 0.1,小数位 1,单位 °C;数值,偏移 6,F32,大端(AB CD)。
  5. 把 AA 55 07 01 01 02 41 20 00 00 6C AA 55 07 02 00 64 3F 80 00 00 2C 粘到测试框,点解码。

解出两帧,都是「正常」:

  • 命令=读数 (1), 温度=25.8 °C, 数值=10
  • 命令=校准 (2), 温度=10.0 °C, 数值=1

长度字节 07 数的是从 01 到 00 这 7 个字节。校验和是 07 + 01 + 01 + 02 + 41 + 20 + 00 + 00 = 0x16C,取低字节 6C,所以「校验」字段显示 0x6C OK。如果显示的是「(应为 …)」,最常见的原因是求和的起点不对:从字节 0 开始求和会把帧头也算进去,结果是 6B。点确定,在连接的解码器里选 传感器 AA55,传感器的帧一到就会被解出来。

导出与复制

  • 复制选中行(在帧表里按 Ctrl+C,或从「导出」菜单、右键菜单选)把选中的行以制表符分隔、带表头放进剪贴板,可直接粘贴到电子表格。
  • 导出 → 导出帧 (CSV)... 每帧一行:序号、时间、方向、对端、协议、状态、长度、原始字节、摘要、配对帧、以毫秒计的延迟,全部字段合在一格里。
  • 导出 → 导出字段 (CSV)... 每个字段一行,带值、偏移、长度和原始字节,正适合做透视表;响应里的寄存器以所属分组命名,如 寄存器 / 40001。

选中了不止一行时只导出选中的行,否则导出整张帧表。文件为 UTF-8 带 BOM,Excel 双击即可打开。列名、方向(TX / RX)和状态(OK、EXCEPTION、CHECKSUM_ERROR、MALFORMED、INCOMPLETE、UNRECOGNIZED)固定为英文,方便对接方的脚本读取;摘要和字段名跟随软件界面语言。默认文件名是端口名加 -frames- 和日期时间。

Free 与 SPU Pro

协议解码视图在 Free 里用于看清它能做什么:

  • 每次启动 SPU 可解码 120 秒,只计解出帧的秒数:某一秒里实时连接至少解出一帧,这一秒就计 1 秒,无论这一秒里有多少连接、多少帧;没有解出帧的秒数不计。窗口里所有连接、所有解码器合计;「无法识别」的行不计,解码器选错了协议也不会被噪声耗掉额度。清空帧表不会退还额度;面板隐藏时不解码,也不计数。面板的状态行显示剩余秒数。第 120 秒用完后解码暂停,直到重启 SPU;接收区照常工作。回放窗口里的解码不计入(见会话回放)。
  • 只有列表中的第一个模板参与解码,其余模板在解码器下拉框和编辑器里标为「(SPU Pro)」,可以用 ↑ 按钮把需要的那个移到最前。所有模板仍然可以编辑,也可以在测试框里试解。
  • 复制选中行免费;CSV 导出需要 SPU Pro。

SPU Pro 没有这些限制。

这篇文档是否有帮助?