Modbus应用层协议的深度剖析

核心结论

协议 物理介质 能否用通用工具测试
Modbus RTU 串口 (232/485) ✅ 串口小助手可以,但只能发原始字节
Modbus TCP 以太网 (网线) ✅ TCP测试工具可以,但只能发原始数据
Modbus ASCII 串口 ✅ 类似RTU,帧格式不同

Modbus RTU 详解

报文格式(十六进制字节流)

设备地址\] \[功能码\] \[数据\] \[CRC16校验

1字节 1字节 N字节 2字节

实例:

复制代码
发送:01 03 00 00 00 03 05 CB
      │  │  │     │     └── CRC校验低字节: 0xCB
      │  │  │     └──────── 寄存器数量: 3
      │  │  └────────────── 起始地址高字节: 0x00
      │  └───────────────── 功能码03: 读保持寄存器
      └──────────────────── 设备地址: 1

串口小助手设置:

端口: COM3

波特率: 9600 (和设备一致)

数据位: 8

停止位: 1

校验: 无/偶校验 (和设备一致)

发送区(HEX模式): 01 03 00 00 00 03 05 CB

接收区(HEX模式): 会看到原始字节回应

Modbus TCP 详解

报文格式(MBAP头 + PDU)

事务ID\] \[协议ID\] \[长度\] \[单元ID\] \[功能码\] \[数据

2字节 2字节 2字节 1字节 1字节 N字节

实例:

复制代码
发送:00 01 00 00 00 06 01 03 00 00 00 03
      │     │     │     │  │  │     └─ 寄存器数量
      │     │     │     │  │  └─────── 起始地址
      │     │     │     │  └───────── 功能码03
      │     │     │     └──────────── 单元ID(设备地址)
      │     │     └────────────────── 后面有6字节
      │     └──────────────────────── 协议ID=0 (Modbus)
      └────────────────────────────── 事务ID=1

| 工具 | 用途 |

| SocketTool / 网络调试助手 | 发原始TCP数据 |

| Modbus Poll | 专业Modbus工具,解析寄存器 |

| telnet IP 502 | 快速测试端口通不通 |

模式: TCP Client

地址: 192.168.1.100 (PLC/设备IP)

端口: 502

发送(HEX): 00 01 00 00 00 06 01 03 00 00 00 03

接收(HEX): 00 01 00 00 00 09 01 03 06 02 2B 00 00 00 64

在使用Modbus通讯协议时,关于通用工具和专用工具的区别:

问题 答案
RTU能用串口小助手吗? ✅ 能,但要手动算CRC、拼字节、解析回应
TCP能用网络调试助手吗? ✅ 能,但要手动拼MBAP头、解析字节
为什么还用专用工具? 专用工具懂协议语义 ,通用工具只传原始字节
写程序要手动拼字节吗? ❌ 不需要,用Modbus库(NModbus/EasyModbus)

一句话:Modbus是"语言",串口/网线是"嘴巴"------你能用任何工具让嘴巴动,但只有懂语言的工具才能明白在说什么。

为什么TCP不需要CRC?

复制代码
RTU:  地址 + PDU + CRC16
      ↑                ↑
      无MBAP头        需要CRC校验(串口可能丢包/干扰)
      
TCP:  MBAP头 + PDU
      ↑        ↑
      有长度字段  TCP自带校验和+重传机制,无需额外CRC
           ↑
      长度字段=冗余校验,若实际长度不符直接丢弃
特性 Modbus RTU Modbus TCP
ADU结构 地址+PDU+CRC MBAP+PDU
地址标识 1字节设备地址 MBAP中的Unit ID
错误校验 CRC16 TCP校验+MBAP长度字段
事务追踪 ❌ 无 ✅ 事务ID匹配请求响应
协议标识 ❌ 无 ✅ 可区分Modbus/其他协议
长度识别 通过计时或字节计数 ✅ MBAP明确指示
多主站 ❌ 半双工总线仲裁难 ✅ TCP天然支持

MBAP头是TCP的"信封" (含邮编、发件人、尺寸),PDU是"信纸内容" (功能码+数据),ADU是完整的"信件"。RTU没有信封,直接在信纸上盖章(CRC)就寄了。

Modbus ASCII

关键 :RTU和ASCII都跑在串口硬件 上(232/485),只是帧格式不同;TCP跑在以太网

模式 数据格式 校验方式 效率 应用场景
Modbus RTU 二进制字节 CRC16 高(紧凑) 工业主流,默认首选
Modbus ASCII ASCII字符 LRC校验 低(冗长) 调试可视、低速串口
Modbus TCP 二进制字节 TCP校验 高(以太网) 现代网络架构

ASCII与RTU的本质区别

特性 Modbus RTU Modbus ASCII
帧头标志 3.5个字符时间静默 : 字符(冒号,0x3A)
数据编码 纯二进制 ASCII十六进制(每个字节拆成2字符)
地址字段 1字节 2字符(如"01")
功能码 1字节 2字符(如"03")
数据区 N字节 2×N字符(十六进制字符串)
校验 CRC16(2字节) LRC(1字节→2字符)
帧尾 3.5个字符时间静默 CR LF(0x0D 0x0A)
帧长度 短(紧凑) 长(翻倍+开销)

实例对比:同一请求的RTU vs ASCII

设备地址1,功能码3,读保持寄存器,起始地址0,数量3

RTU帧(二进制,8字节)

复制代码
十六进制:  01    03    00 00    00 03    05 CB
           │     │     │        │        └── CRC16
           │     │     │        └── 数量=3
           │     │     └── 起始地址=0
           │     └── 功能码=03
           └── 地址=1

原始字节流: [0x01][0x03][0x00][0x00][0x00][0x03][0x05][0xCB]
           └── 不可读,需十六进制工具查看

串口监视器显示01 03 00 00 00 03 05 CB(乱码或空白)

ASCII帧(字符,17字节)

复制代码
字符流:   :   0   1   0   3   0   0   0   0   0   0   0   3   F   A   CR LF
         │   └───┬───┘   └───┬───┘   └───────┬───────┘   └───┘   └──┬──┘
         │    地址=1      功能码=03      地址0+数量3       LRC校验   结束
        帧头冒号

十六进制字节流:
[0x3A][0x30][0x31][0x30][0x33][0x30][0x30][0x30][0x30][0x30][0x30][0x30][0x33][0x46][0x41][0x0D][0x0A]

人类可读形式: `:010300000003FA` 然后回车换行

串口小助手显示:010300000003FA(可直接阅读!)

ASCII的具体编码规则

字节 → ASCII转换

原始字节 ASCII表示 计算
0x01 "01" 高4位=0→'0'(0x30),低4位=1→'1'(0x31)
0xAB "AB" 高4位=A→'A'(0x41),低4位=B→'B'(0x42)
0xFF "FF" 都是F→'F'(0x46)

对比CRC16:LRC是简单累加和,CRC是多项式除法,后者更可靠。

ASCII的优势与劣势

唯一优势:人类可读性

复制代码
场景:调试现场只有串口小助手/超级终端

RTU显示:  □☻   (乱码,看不出内容)
ASCII显示: :010300000003FA  (一目了然!)

操作工可以直接抄下报文,用纸笔计算验证。

显著劣势

问题 说明 量化
带宽浪费 每个字节变2字符,还要加:和CRLF 数据量翻倍+3字节开销
解析延迟 必须等CRLF才能确定帧结束 实时性差
传输效率 同样波特率,吞吐量约为RTU的1/2 9600bps下约480字符/秒
设备支持 现代设备多已取消ASCII支持 兼容性问题

硬件基础:和RTU完全一致

复制代码
┌─────────────────────────────────────────┐
│           应用层:Modbus协议              │
│      (RTU/ASCII/TCP选择帧格式)          │
├─────────────────────────────────────────┤
│           传输层:UART串口时序             │
│      (波特率/数据位/停止位/校验位)      │
├─────────────────────────────────────────┤
│           物理层:RS-232 或 RS-485        │
│      (电气特性、线缆、拓扑)              │
└─────────────────────────────────────────┘
           ↑
    ASCII和RTU在这里完全一致!
参数 ASCII模式 RTU模式
波特率 常用9600(可更低,如1200) 常用9600~115200
数据位 7位或8位(必须7位!) 8位
停止位 1位 1位
校验 偶校验(必须!) 偶校验/无校验
流控

何时还在用ASCII?

场景 原因
老旧设备 80年代的PLC只支持ASCII
电话线Modem 早期远程拨号通信,ASCII容错更好
调试工具 某些串口监视器自动解析ASCII模式
教学演示 让学生直观看到报文结构
特殊网关 串口转短信/串口转打印机等低速场景

现代工业现状:新项目99%用RTU,以太网普及后用TCP。ASCII基本被淘汰。

Modbus ASCII是用"人类可读字符"包裹的二进制协议,和RTU跑在同一根串口线上,只是把所有字节掰成两半写成十六进制字符串,牺牲了效率换取调试便利。它是Modbus的"明文模式"

相关推荐
yunfuuwqi3 小时前
OpenClaw✅真·喂饭级教程:2026年OpenClaw(原Moltbot)一键部署+接入飞书最佳实践
运维·服务器·网络·人工智能·飞书·京东云
迎仔3 小时前
C-算力中心网络隔离实施方法:怎么搞?
运维·网络
代码游侠3 小时前
C语言核心概念复习——网络协议与TCP/IP
linux·运维·服务器·网络·算法
R1nG8634 小时前
HCCL vs NCCL代码级对比 hccl/algorithms/ vs nccl/src/collectives/ Ring算法实现差异
wpf·cann
枷锁—sha4 小时前
【SRC】SQL注入WAF 绕过应对策略(二)
网络·数据库·python·sql·安全·网络安全
Zach_yuan5 小时前
深入浅出 JSONCpp
linux·服务器·网络·c++
刘欣的博客5 小时前
C# CS架构程序发版升级的走数据库方案
c#·单文件升级自己的方式
Yorlen_Zhang6 小时前
Python Tkinter Text 控件完全指南:从基础编辑器到富文本应用
开发语言·python·c#
迎仔6 小时前
B-算力中心网络隔离的必要性:为什么必须隔离?
网络