提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、Modbus 协议的 4 种寄存器
- 二、Modbus协议功能码详细介绍
-
- 1.读操作功能码
- 2.写操作功能码
- 3.特殊功能码
- 三、Modbus协议三种传输模式详细介绍
-
- 1.RTU模式(Remote Terminal Unit)
-
- 1.1 功能码 0x01 – 读线圈状态
- 1.2 功能码 0x02 – 读离散输入状态
- 1.3 功能码 0x03 – 读保持寄存器
- 1.4 功能码 0x04 – 读输入寄存器
- 1.5 功能码 0x05 – 写单个线圈
- 1.7 功能码 0x06 – 写单个保持寄存器
- 1.8 功能码 0x0F (15) – 写多个线圈
- 1.9 功能码 0x10 (16) – 写多个保持寄存器
- 1.10 功能码 0x07 – 报告从设备ID
- 1.11 功能码 0x08 – 诊断(子功能码0x0000 – 回显测试)
- 1.12 功能码 0x16 (22) – 掩码写寄存器
- 1.13 功能码 0x17 (23) – 读写多个寄存器
- 2.ASCII模式(American Standard Code for Information Interchange)
-
- 1.1 ASCII编码对照表
- 1.2 功能码0x03 – 读保持寄存器
- 1.3 功能码0x06 – 写单个保持寄存器
- 3.TCP模式(Transmission Control Protocol)
-
- 1.1 Modbus TCP模式与RTU模式报文区别
- 1.2 功能码0x03 – 读保持寄存器
前言
Modbus协议的四大核心要素——寄存器类型、功能码、传输模式、物理介质——构成了一个完整的分层通信体系,它们之间的关系可以概括为:
寄存器类型定义了“操作对象是什么”,是Modbus协议的数据基础,代表了工业现场中线圈、离散输入、保持寄存器、输入寄存器这四种不同性质的物理数据。功能码定义了“执行什么操作”,是与寄存器类型强绑定的操作指令——读线圈必须用01,读保持寄存器必须用03,这种绑定关系确保了设备能正确理解主站的意图。传输模式定义了“数据如何表示和定界”,RTU用二进制编码和时间间隔定界,效率高、校验强;ASCII用文本编码和特殊字符定界,可读性好、容错性强;TCP则通过以太网传输,去掉了CRC校验,增加了MBAP报文头。物理介质定义了“用什么传”,RS-232适合点对点短距离,RS-485适合多点长距离,以太网适合高速网络化通信。
这四者不是孤立的:寄存器类型和功能码构成了应用层的核心,决定了通信的内容和意图;传输模式属于表示层,决定了数据的呈现形式;物理介质属于物理层,决定了信号的传输载体。一个完整的Modbus通信,需要根据现场需求选择合适的寄存器类型、搭配正确的功能码、选用恰当的传输模式、连接匹配的物理介质,四者协同工作,才能实现可靠的数据交换。理解它们之间的层级关系和内在联系,是掌握Modbus协议的关键所在。
#mermaid-svg-IaMo2DRbzL1mUcNi{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-IaMo2DRbzL1mUcNi .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-IaMo2DRbzL1mUcNi .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-IaMo2DRbzL1mUcNi .error-icon{fill:#552222;}#mermaid-svg-IaMo2DRbzL1mUcNi .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-IaMo2DRbzL1mUcNi .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-IaMo2DRbzL1mUcNi .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-IaMo2DRbzL1mUcNi .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-IaMo2DRbzL1mUcNi .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-IaMo2DRbzL1mUcNi .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-IaMo2DRbzL1mUcNi .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-IaMo2DRbzL1mUcNi .marker{fill:#333333;stroke:#333333;}#mermaid-svg-IaMo2DRbzL1mUcNi .marker.cross{stroke:#333333;}#mermaid-svg-IaMo2DRbzL1mUcNi svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-IaMo2DRbzL1mUcNi p{margin:0;}#mermaid-svg-IaMo2DRbzL1mUcNi g.classGroup text{fill:#9370DB;stroke:none;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-IaMo2DRbzL1mUcNi g.classGroup text .title{font-weight:bolder;}#mermaid-svg-IaMo2DRbzL1mUcNi .cluster-label text{fill:#333;}#mermaid-svg-IaMo2DRbzL1mUcNi .cluster-label span{color:#333;}#mermaid-svg-IaMo2DRbzL1mUcNi .cluster-label span p{background-color:transparent;}#mermaid-svg-IaMo2DRbzL1mUcNi .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-IaMo2DRbzL1mUcNi .cluster text{fill:#333;}#mermaid-svg-IaMo2DRbzL1mUcNi .cluster span{color:#333;}#mermaid-svg-IaMo2DRbzL1mUcNi .nodeLabel,#mermaid-svg-IaMo2DRbzL1mUcNi .edgeLabel{color:#131300;}#mermaid-svg-IaMo2DRbzL1mUcNi .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-IaMo2DRbzL1mUcNi .label text{fill:#131300;}#mermaid-svg-IaMo2DRbzL1mUcNi .labelBkg{background:#ECECFF;}#mermaid-svg-IaMo2DRbzL1mUcNi .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-IaMo2DRbzL1mUcNi .classTitle{font-weight:bolder;}#mermaid-svg-IaMo2DRbzL1mUcNi .node rect,#mermaid-svg-IaMo2DRbzL1mUcNi .node circle,#mermaid-svg-IaMo2DRbzL1mUcNi .node ellipse,#mermaid-svg-IaMo2DRbzL1mUcNi .node polygon,#mermaid-svg-IaMo2DRbzL1mUcNi .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-IaMo2DRbzL1mUcNi .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-IaMo2DRbzL1mUcNi g.clickable{cursor:pointer;}#mermaid-svg-IaMo2DRbzL1mUcNi g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-IaMo2DRbzL1mUcNi g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-IaMo2DRbzL1mUcNi .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-IaMo2DRbzL1mUcNi .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-IaMo2DRbzL1mUcNi .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-IaMo2DRbzL1mUcNi .dashed-line{stroke-dasharray:3;}#mermaid-svg-IaMo2DRbzL1mUcNi .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-IaMo2DRbzL1mUcNi #compositionStart,#mermaid-svg-IaMo2DRbzL1mUcNi .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-IaMo2DRbzL1mUcNi #compositionEnd,#mermaid-svg-IaMo2DRbzL1mUcNi .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-IaMo2DRbzL1mUcNi #dependencyStart,#mermaid-svg-IaMo2DRbzL1mUcNi .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-IaMo2DRbzL1mUcNi #dependencyStart,#mermaid-svg-IaMo2DRbzL1mUcNi .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-IaMo2DRbzL1mUcNi #extensionStart,#mermaid-svg-IaMo2DRbzL1mUcNi .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-IaMo2DRbzL1mUcNi #extensionEnd,#mermaid-svg-IaMo2DRbzL1mUcNi .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-IaMo2DRbzL1mUcNi #aggregationStart,#mermaid-svg-IaMo2DRbzL1mUcNi .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-IaMo2DRbzL1mUcNi #aggregationEnd,#mermaid-svg-IaMo2DRbzL1mUcNi .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-IaMo2DRbzL1mUcNi #lollipopStart,#mermaid-svg-IaMo2DRbzL1mUcNi .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-IaMo2DRbzL1mUcNi #lollipopEnd,#mermaid-svg-IaMo2DRbzL1mUcNi .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-IaMo2DRbzL1mUcNi .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-IaMo2DRbzL1mUcNi .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-IaMo2DRbzL1mUcNi .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-IaMo2DRbzL1mUcNi .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-IaMo2DRbzL1mUcNi :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
功能码指定操作对象
数据通过传输模式封装
封装后的数据通过介质传输
«功能码»
应用层
定义:读什么?写什么?读线圈还是读寄存器?
01必须配合线圈
03必须配合保持寄存器
功能码与寄存器强绑定
读操作:01(读线圈) 02(读离散输入) 03(读保持寄存器) 04(读输入寄存器)
写操作:05(写单线圈) 06(写单寄存器) 15(写多线圈) 16(写多寄存器)
诊断:07(报告ID) 08(诊断) 22(掩码写) 23(读写)
«寄存器类型»
数据层
定义:操作的数据是什么类型?开关量还是模拟量?
线圈:1位,可读可写,控制继电器等
离散输入:1位,只读,读取按钮状态等
保持寄存器:16位,可读可写,设定参数等
输入寄存器:16位,只读,采集温度等
四种类型代表不同物理存储区
读写权限由硬件决定
«传输模式»
表示层
定义:数据如何编码?用二进制还是文本?
RTU:二进制编码,时间间隔定界,CRC校验
ASCII:文本编码,特殊字符定界,LRC校验
TCP:二进制编码,长度字段定界,无额外校验
RTU适合工业现场
ASCII适合调试环境
TCP适合物联网
«物理介质»
物理层
定义:用什么线?什么接口?
以太网:高速,远距离,可联网
串口只能用RTU/ASCII
以太网只能用TCP
RS-232:点对点,传输距离短(15米)
RS-485:多点通信,传输距离长(1200米)
一、Modbus 协议的 4 种寄存器
Modbus 协议的 4 种寄存器,是工业通信中用来区分不同数据类型的标准。理解它们的关键,是分清 “类型” (干什么用)和 “地址” (怎么找到它),以及把握读写属性。
| 线圈(Coils) | 1位(Bit) | 可读可写 | 控制继电器启停、电磁阀开关、指示灯亮灭 | 0x01 / 0x05, 0x0F | 00001 – 09999 | 0 – 9998 |
| 离散输入(Discrete Inputs) | 1位(Bit) | 只读 | 读取限位开关状态、按钮是否按下、传感器触发信号 | 0x02 / 不支持 | 10001 – 19999 | 0 – 9998 |
| 保持寄存器(Holding Registers) | 16位(Word) | 可读可写 | 读取或修改PID参数、设定温度值、电机转速、累加器数值 | 0x03 / 0x06, 0x10 | 40001 – 49999 | 0 – 9998 |
| 输入寄存器(Input Registers) | 16位(Word) | 只读 | 读取实时温度、压力、流量、电压、电流等模拟量采集值 | 0x04 / 不支持 | 30001 – 39999 | 0 – 9998 |
计算地址举例说明:
保持寄存器 40001:起始地址是40001。计算公式:40001 – 40001 = 0。所以,通讯时使用的地址是 0。
保持寄存器 40010:计算公式:40010 – 40001 = 9。所以,通讯时使用的地址是 9。
注意:有时会出现Modulus设备制造商为了简化编程和通信,会将所有数据(包括本应放在线圈、离散输入、输入寄存器的数据)全部映射到保持寄存器区域。这意味着:原本用01功能码读的线圈状态(开关量),原本用02功能码读的离散输入(按钮状态),原本用04功能码读的输入寄存器(模拟量采集值),都可以统一用03功能码从保持寄存器中读取。此时地址就是实际地址不需计算。
二、Modbus协议功能码详细介绍
Modbus功能码是协议的核心指令,位于报文帧中的第2个字节,用于告诉从设备需要执行什么操作。以下从分类、详解、报文结构、异常处理等方面进行全面介绍。
1.读操作功能码
| 0x01 | 读线圈状态 | 线圈(可读写) | 2000个 | 监控继电器、开关状态 |
| 0x02 | 读离散输入状态 | 离散输入(只读) | 2000个 | 读取按钮、传感器触发信号 |
| 0x03 | 读保持寄存器 | 保持寄存器(可读写) | 125个字 | 读取设备参数、运行数据 |
| 0x04 | 读输入寄存器 | 输入寄存器(只读) | 125个字 | 采集模拟量(温度、压力等) |
2.写操作功能码
| 0x05 | 写单个线圈 | 单个线圈 | 1个 | 控制单个设备启停 |
| 0x06 | 写单个保持寄存器 | 单个保持寄存器 | 1个 | 修改单个参数(如设定值) |
| 0x0F (15) | 写多个线圈 | 多个线圈 | 1968个 | 批量控制开关组 |
| 0x10 (16) | 写多个保持寄存器 | 多个保持寄存器 | 123个字 | 批量配置参数 |
3.特殊功能码
| 0x07 | 报告从设备ID | 获取从设备的标识信息 |
| 0x08 | 诊断 | 通信链路测试、错误检测 |
| 0x16 (22) | 掩码写寄存器 | 对寄存器的指定位进行掩码修改 |
| 0x17 (23) | 读写多个寄存器 | 同时读取和写入,高效操作 |
三、Modbus协议三种传输模式详细介绍
Modbus协议定义了三种传输模式:RTU、ASCII和TCP。其中RTU和ASCII用于串行通信(RS-232/RS-485),TCP用于以太网通信。同一网络中所有设备必须使用相同的传输模式。
1.RTU模式(Remote Terminal Unit)
RTU是Modbus串行通信中最常用的模式,数据以二进制格式直接传输,效率最高。在相同波特率下,RTU模式比ASCII模式能传送更多数据。
RTU模式完整传输:[静默时间] + [报文内容] + [静默时间] 静默时间是指Modbus RTU模式中,串行通信线路上没有数据发送的空闲状态,用于标识一个报文帧的起始和结束,通常在通信软件里面设置。静默时间阈值 = 3.5 × 1字符时间,通常报文传输时≥ 静默时间阈值(3.5字符时间)。 常见配置:9600bps,8数据位,1停止位,无校验 字符帧格式:1起始位 + 8数据位 + 0校验位 + 1停止位 = 10位 1字符时间 = 10位 / 9600bps = 1.041666…ms ≈ 1.04ms 3.5字符时间 = 3.5 × 1.0417ms = 3.6458ms ≈ 3.65ms 1.5字符时间 = 1.5 × 1.0417ms = 1.5625ms ≈ 1.56ms
报文内容是包含:设备地址 功能码 起始地址高位 起始地址低位 线圈数量高位 线圈数量低位 CRC校验低位 CRC校验高位
1.1 功能码 0x01 – 读线圈状态
功能:读取从站线圈(可读写开关量)的当前状态 举例请求报文:01 01 00 00 00 0A 3D C9
| 值(Hex) | 01 | 01 | 00 | 00 | 00 | 0A | 3D | C9 |
| 说明 | 目标从站地址,范围1-247 | 读线圈状态 | 起始地址的高8位 | 起始地址的低8位 | 读取数量的高8位 | 读取数量的低8位 | CRC-16校验值低8位 | CRC-16校验值高8位 |
响应报文:01 01 02 CD 01 85 37
| 值(Hex) | 01 | 01 | 02 | CD | 01 | 85 | 37 |
| 说明 | 原从站地址返回 | 原功能码返回 | 后续数据的字节数,10个线圈需2字节存储 | 线圈0-7的状态 | 线圈8-15的状态 | CRC-16低8位 | CRC-16高8位 |
1.2 功能码 0x02 – 读离散输入状态
功能:读取从站离散输入(只读开关量)的当前状态 请求报文:01 02 00 00 00 08 79 CC
| 值(Hex) | 01 | 02 | 00 | 00 | 00 | 08 | 79 | CC |
| 说明 | 目标从站地址1 | 读离散输入状态 | 起始地址的高8位 | 起始地址的低8位,组合0x0000(离散输入10001) | 读取数量的高8位 | 读取数量的低8位,组合0x0008=8个 | CRC-16校验值低8位 | CRC-16校验值高8位 |
响应报文:01 02 01 A5 E0 2A
| 值(Hex) | 01 | 02 | 01 | A5 | E0 | 2A |
| 说明 | 原从站地址返回 | 原功能码返回 | 后续数据字节数,8个输入需1字节 | 输入0-7状态 | CRC-16校验值低8位 | CRC-16校验值高8位 |
1.3 功能码 0x03 – 读保持寄存器
功能:读取从站保持寄存器(可读写16位数据)
请求报文:01 03 00 00 00 03 05 CB
| 值(Hex) | 01 | 03 | 00 | 00 | 00 | 03 | 05 | CB |
| 说明 | 目标从站地址1 | 读保持寄存器 | 起始地址的高8位 | 起始地址的低8位,组合0x0000(保持寄存器40001) | 读取数量的高8位 | 读取数量的低8位,组合0x0003=3个 | CRC-16校验值低8位 | CRC-16校验值高8位 |
注:寄存器数量指的是读取多少个寄存器
响应报文:01 03 06 12 34 56 78 9A BC 51 C0
| 值(Hex) | 01 | 03 | 06 | 12 | 34 | 56 | 78 | 9A | BC | 51 | C0 |
| 说明 | 原地址返回 | 原功能码返回 | 后续字节数,3个寄存器×2=6字节 | 寄存器1高8位 | 寄存器1低8位,组合0x1234 | 寄存器2高8位 | 寄存器2低8位,组合0x5678 | 寄存器3高8位 | 寄存器3低8位,组合0x9ABC | CRC低8位 | CRC高8位 |
1.4 功能码 0x04 – 读输入寄存器
功能:读取从站输入寄存器(只读16位模拟量)
请求报文:01 04 00 00 00 02 71 CB
| 值(Hex) | 01 | 04 | 00 | 00 | 00 | 02 | 71 | CB |
| 说明 | 目标从站地址1 | 读输入寄存器 | 起始地址的高8位 | 起始地址的低8位,组合0x0000(输入寄存器30001) | 读取数量的高8位 | 读取数量的低8位,组合0x0002=2个 | CRC-16校验值低8位 | CRC-16校验值高8位 |
响应报文:01 04 04 00 64 01 F4 7A 59
| 值(Hex) | 01 | 04 | 04 | 00 | 64 | 01 | F4 | 7A | 59 |
| 说明 | 原地址返回 | 原功能码返回 | 后续字节数,2个寄存器×2=4字节 | 寄存器1高8位 | 寄存器1低8位,组合0x0064=100 | 寄存器2高8位 | 寄存器2低8位,组合0x01F4=500 | CRC低8位 | CRC高8位 |
1.5 功能码 0x05 – 写单个线圈
功能:写入单个线圈的ON/OFF状态
请求报文 :01 05 00 00 FF 00 8C 3A
| 值(Hex) | 01 | 05 | 00 | 00 | FF | 00 | 8C | 3A |
| 说明 | 目标从站地址1 | 写单个线圈 | 线圈地址的高8位 | 线圈地址的低8位,组合0x0000(线圈00001) | FF00表示ON | 固定为0x00 | CRC-16校验值低8位 | CRC-16校验值高8位 |
响应报文:与请求报文完全相同(回显确认)
| 值(Hex) | 01 | 05 | 00 | 00 | FF | 00 | 8C | 3A |
| 说明 | 原从站地址返回 | 原功能码返回 | 确认线圈地址高8位 | 确认线圈地址低8位 | 确认写入值高8位 | 确认写入值低8位 | CRC-16校验值低8位 | CRC-16校验值高8位 |
1.7 功能码 0x06 – 写单个保持寄存器
功能:写入单个保持寄存器的16位数值
请求报文:01 06 00 01 12 34 D4 3D
| 值(Hex) | 01 | 06 | 00 | 01 | 12 | 34 | D4 | 3D |
| 说明 | 目标从站地址1 | 写单个寄存器 | 寄存器地址高8位 | 寄存器地址低8位,组合0x0001(保持寄存器40002) | 写入值高8位 | 写入值低8位,组合0x1234=4660 | CRC-16校验值低8位 | CRC-16校验值高8位 |
注:寄存器值指的是把这个寄存器的值1234写入寄存器地址0001中
响应报文:与请求报文完全相同(回显确认)
| 值(Hex) | 01 | 06 | 00 | 01 | 12 | 34 | D4 | 3D |
| 说明 | 原从站地址返回 | 原功能码返回 | 确认地址高8位 | 确认地址低8位 | 确认值高8位 | 确认值低8位 | CRC-16校验值低8位 | CRC-16校验值高8位 |
1.8 功能码 0x0F (15) – 写多个线圈
功能:连续写入多个线圈的状态
请求报文:01 0F 00 00 00 0A 02 CD 01 5F E6
| 值(Hex) | 01 | 0F | 00 | 00 | 00 | 0A | 02 | CD | 01 | 5F | E6 |
| 说明 | 目标地址1 | 写多个线圈 | 起始地址高8位 | 起始地址低8位,组合0x0000 | 数量高8位 | 数量低8位,10个线圈 | 后续数据字节数 | 线圈0-7:11001101 | 线圈8-15:00000001 | CRC低8位 | CRC高8位 |
注:这段报文的意思是写10个线圈到0000地址中,写的数值为CD01
响应报文:01 0F 00 00 00 0A 14 0F
| 值(Hex) | 01 | 0F | 00 | 00 | 00 | 0A | 14 | 0F |
| 说明 | 原地址返回 | 原功能码返回 | 确认起始地址高8位 | 确认起始地址低8位 | 确认数量高8位 | 确认数量低8位 | CRC-16校验值低8位 | CRC-16校验值高8位 |
1.9 功能码 0x10 (16) – 写多个保持寄存器
功能:连续写入多个保持寄存器的值
请求报文:01 10 00 00 00 03 06 00 01 00 02 00 03 E7 64
| 值(Hex) | 01 | 10 | 00 | 00 | 00 | 03 | 06 | 00 | 01 | 00 | 02 | 00 | 03 | E7 | 64 |
| 说明 | 目标地址1 | 写多个寄存器 | 起始地址高8位 | 起始地址低8位,0x0000 | 数量高8位 | 数量低8位,3个 | 后续字节数,3×2=6 | 寄存器1高8位 | 寄存器1低8位,0x0001=1 | 寄存器2高8位 | 寄存器2低8位,0x0002=2 | 寄存器3高8位 | 寄存器3低8位,0x0003=3 | CRC低8位 | CRC高8位 |
注:这段报文的意思是从地址0000开始写,写3个寄存器,3个寄存器共占6个字节,寄存器1 2 3 分别存储每个数据的值
响应报文:01 10 00 00 00 03 01 CB
| 值(Hex) | 01 | 10 | 00 | 00 | 00 | 03 | 01 | CB |
| 说明 | 原地址返回 | 原功能码返回 | 确认起始地址高8位 | 确认起始地址低8位 | 确认数量高8位 | 确认数量低8位 | CRC-16校验值低8位 | CRC-16校验值高8位 |
1.10 功能码 0x07 – 报告从设备ID
功能:获取从设备的ID信息
请求报文:01 07 40 92
| 值(Hex) | 01 | 07 | 40 | 92 |
| 说明 | 目标从站地址,范围1-247 | 报告从设备ID,获取设备标识信息 | CRC-16校验值低8位 | CRC-16校验值高8位 |
响应报文:01 07 05 01 54 65 73 74 01 20 1D
| 值(Hex) | 01 | 07 | 05 | 01 | 54 | 65 | 73 | 74 | 01 | 20 |
| 说明 | 原从站地址返回 | 原功能码返回 | 后续数据的字节数,本例为5字节 | 设备ID号,厂商自定义 | 运行状态,0x54='T’表示运行中(Running) | 额外ASCII数据,0x65=‘e’ | 额外ASCII数据,0x73=‘s’ | 额外ASCII数据,0x74=‘t’,组合为"Test" | CRC-16校验值低8位 | CRC-16校验值高8位 |
1.11 功能码 0x08 – 诊断(子功能码0x0000 – 回显测试)
功能:通信链路测试,从站原样返回请求数据
请求报文:01 08 00 00 A5 5A 57 10
| 值(Hex) | 01 | 08 | 00 | 00 | A5 | 5A | 57 | 10 |
| 说明 | 目标从站地址1 | 诊断功能 | 子功能码高8位 | 子功能码低8位,0x0000=回显测试(Query) | 测试数据高8位,可任意值 | 测试数据低8位,可任意值 | CRC-16校验值低8位 | CRC-16校验值高8位 |
响应报文:与请求报文完全相同
| 值(Hex) | 01 | 08 | 00 | 00 | A5 | 5A | 57 | 10 |
| 说明 | 原从站地址返回 | 原功能码返回 | 确认子功能码高8位 | 确认子功能码低8位,0x0000 | 原样返回测试数据高8位 | 原样返回测试数据低8位 | CRC-16校验值低8位 | CRC-16校验值高8位 |
1.12 功能码 0x16 (22) – 掩码写寄存器
功能:对寄存器的指定位进行AND/OR掩码修改(无需读取整个寄存器)
请求报文:01 16 00 00 00 FF 00 12 AC 3F
| 值(Hex) | 01 | 16 | 00 | 00 | 00 | FF | 00 | 12 | AC | 3F |
| 说明 | 目标从站地址1 | 掩码写寄存器(22) | 寄存器地址高8位 | 寄存器地址低8位,组合0x0000(保持寄存器40001) | AND掩码高8位 | AND掩码低8位,组合0x00FF | OR掩码高8位 | OR掩码低8位,组合0x0012 | CRC-16校验值低8位 | CRC-16校验值高8位 |
响应报文:与请求报文完全相同(回显确认)
| 值(Hex) | 01 | 16 | 00 | 00 | 00 | FF | 00 | 12 | AC | 3F |
| 说明 | 原从站地址返回 | 原功能码返回 | 确认寄存器地址高8位 | 确认寄存器地址低8位 | 确认AND掩码高8位 | 确认AND掩码低8位 | 确认OR掩码高8位 | 确认OR掩码低8位 | CRC-16校验值低8位 | CRC-16校验值高8位 |
1.13 功能码 0x17 (23) – 读写多个寄存器
功能:在一次通信中同时完成读取和写入操作
请求报文:01 17 00 00 00 02 00 02 00 02 04 00 01 00 02 4C 57
| 值(Hex) | 01 | 17 | 00 | 00 | 00 | 02 | 00 | 02 | 00 | 02 | 04 | 00 | 01 | 00 | 02 | 4C | 57 |
| 说明 | 目标地址1 | 读写寄存器(23) | 读取起始地址高8位 | 读取起始地址低8位,0x0000 | 读取寄存器数量高8位 | 读取寄存器数量低8位,0x0002=2个 | 写入起始地址高8位 | 写入起始地址低8位,0x0002 | 写入寄存器数量高8位 | 写入寄存器数量低8位,0x0002=2个 | 写入数据字节数,2×2=4 | 写入寄存器1高8位 | 写入寄存器1低8位,0x0001=1 | 写入寄存器2高8位 | 写入寄存器2低8位,0x0002=2 | CRC-16低8位 | CRC-16高8位 |
响应报文:01 17 04 12 34 56 78 24 D8
| 值(Hex) | 01 | 17 | 04 | 12 | 34 | 56 | 78 | 24 | D8 |
| 说明 | 原从站地址返回 | 原功能码返回 | 读取到的数据字节数,2×2=4字节 | 读取的寄存器1高8位 | 读取的寄存器1低8位,组合0x1234 | 读取的寄存器2高8位 | 读取的寄存器2低8位,组合0x5678 | CRC-16校验值低8位 | CRC-16校验值高8位 |
2.ASCII模式(American Standard Code for Information Interchange)
ASCII模式将每个8位字节拆分为两个ASCII字符(十六进制表示)进行传输。例如,数值0x3F会作为字符’3’(0x33)和’F’(0x46)发送。此模式的主要优点是允许字符间间隔长达1秒而不产生错误。
1.1 ASCII编码对照表
| 0x30 | ‘0’ | 0x38 | ‘8’ |
| 0x31 | ‘1’ | 0x39 | ‘9’ |
| 0x32 | ‘2’ | 0x41 | ‘A’ |
| 0x33 | ‘3’ | 0x42 | ‘B’ |
| 0x34 | ‘4’ | 0x43 | ‘C’ |
| 0x35 | ‘5’ | 0x44 | ‘D’ |
| 0x36 | ‘6’ | 0x45 | ‘E’ |
| 0x37 | ‘7’ | 0x46 | ‘F’ |
1.2 功能码0x03 – 读保持寄存器
说明:读取从站地址1、起始地址0(40001)、2个保持寄存器
请求报文ASCII显示:: 0 1 0 3 0 0 0 0 0 0 0 2 L R C CR LF 十六进制:3A 30 31 30 33 30 30 30 30 30 30 30 32 4C 52 43 0D 0A
| 设备地址 | 0 1 | 30 31 | 2字符 | 从站地址=0x01 |
| 功能码 | 0 3 | 30 33 | 2字符 | 读保持寄存器=0x03 |
| 起始地址 | 0 0 0 0 | 30 30 30 30 | 4字符 | 起始地址=0x0000 |
| 寄存器数量 | 0 0 0 2 | 30 30 30 32 | 4字符 | 读取2个寄存器=0x0002 |
| LRC校验 | L R C | 4C 52 43 | 3字符 | 注意:示例中"LRC"为占位,实际为计算值,占1个字符 |
注:起始标志(:)与结束标志(LF)并不是报文内容,报文内容:0 1 0 3 0 0 0 0 0 0 0 2 L R C,L R C计算时只计算报文内容部分。 ASCII模式完整传输:[起始标志 :] + [报文内容] + [结束标志 CR+LF] RTU模式完整传输:[静默时间] + [报文内容] + [静默时间]
响应报文
ASCII显示:: 0 1 0 3 0 4 0 0 0 A 0 0 0 5 L R C CR LF 十六进制:3A 30 31 30 33 30 34 30 30 30 41 30 30 30 35 4C 52 43 0D 0A
| 设备地址 | 0 1 | 30 31 | 2字符 | 原从站地址=0x01 |
| 功能码 | 0 3 | 30 33 | 2字符 | 原功能码=0x03 |
| 数据字节数 | 0 4 | 30 34 | 2字符 | 后续数据4字节=0x04 |
| 寄存器1高位 | 0 0 | 30 30 | 2字符 | 0x00 |
| 寄存器1低位 | 0 A | 30 41 | 2字符 | 0x0A,组合0x000A=10 |
| 寄存器2高位 | 0 0 | 30 30 | 2字符 | 0x00 |
| 寄存器2低位 | 0 5 | 30 35 | 2字符 | 0x05,组合0x0005=5 |
| LRC校验 | L R C | 4C 52 43 | 3字符 | 纵向冗余校验值,实际计算时占1个字符 |
1.3 功能码0x06 – 写单个保持寄存器
说明:向从站地址1、地址0(40001)写入值0x0012 ASCII显示:: 0 1 0 6 0 0 0 0 0 0 1 2 L R C CR LF 十六进制:3A 30 31 30 36 30 30 30 30 30 30 31 32 4C 52 43 0D 0A
| 设备地址 | 0 1 | 30 31 | 2字符 | 从站地址=0x01 |
| 功能码 | 0 6 | 30 36 | 2字符 | 写单个寄存器=0x06 |
| 寄存器地址 | 0 0 0 0 | 30 30 30 30 | 4字符 | 寄存器地址=0x0000 |
| 寄存器值 | 0 0 1 2 | 30 30 31 32 | 4字符 | 写入值=0x0012=18 |
| LRC校验 | L R C | 4C 52 43 | 3字符 | 纵向冗余校验值,实际计算时占1个字符 |
响应报文 ASCII显示:: 0 1 0 6 0 0 0 0 0 0 1 2 L R C CR LF 十六进制:3A 30 31 30 36 30 30 30 30 30 30 31 32 4C 52 43 0D 0A 响应报文与请求报文完全相同(回显确认)。 其余功能码不过多阐述,原理参考RTU。
3.TCP模式(Transmission Control Protocol)
Modbus TCP将Modbus协议封装在TCP/IP报文中进行以太网传输。它由施耐德公司于1999年开发,解决了串行通信的距离和速度限制问题。
1.1 Modbus TCP模式与RTU模式报文区别
RTU模式帧结构:[设备地址 1B] [功能码 1B] [数据域 nB] [CRC校验 2B] TCP模式帧结构:[MBAP Header 7B] [功能码 1B] [数据域 nB]
| 报文头 | MBAP Header(7字节) | 无(直接以设备地址开头) |
| 地址字段 | 单元标识符(1字节) | 设备地址(1字节) |
| 功能码 | 1字节 | 1字节 |
| 数据域 | n字节 | n字节 |
| 校验字段 | 无(依赖TCP/IP) | CRC-16(2字节) |
| 总报文长度 | 12字节 + 数据域 | 4字节 + 数据域 + 2字节CRC |
1.2 功能码0x03 – 读保持寄存器
注:读取单元标识符1、起始地址0(40001)、2个保持寄存器 请求报文十六进制:00 01 00 00 00 06 01 03 00 00 00 02
| 事务标识符高位 | 1字节 | 00 | 事务ID高8位 |
| 事务标识符低位 | 1字节 | 01 | 事务ID低8位,组合0x0001,本次请求的标识 |
| 协议标识符高位 | 1字节 | 00 | 协议ID高8位 |
| 协议标识符低位 | 1字节 | 00 | 协议ID低8位,组合0x0000,固定为Modbus协议 |
| 长度高位 | 1字节 | 00 | 后续字节长度高8位 |
| 长度低位 | 1字节 | 06 | 后续字节长度低8位,组合0x0006=6字节(单元标识符1+功能码1+起始地址2+寄存器数量2) |
| 单元标识符 | 1字节 | 01 | 从站地址,用于网关透传,范围1-247 |
| 功能码 | 1字节 | 03 | 读保持寄存器 |
| 起始地址高位 | 1字节 | 00 | 起始寄存器地址高8位 |
| 起始地址低位 | 1字节 | 00 | 起始寄存器地址低8位,组合0x0000(对应PLC地址40001) |
| 寄存器数量高位 | 1字节 | 00 | 读取数量高8位 |
| 寄存器数量低位 | 1字节 | 02 | 读取数量低8位,组合0x0002=2个寄存器 |
注:RTU模式的帧定界为3.5字符静默时间,TCP模式的帧定界为长度字段 + TCP连接 。
响应报文
| 事务标识符高位 | 1字节 | 00 | 事务ID高8位,与请求相同 |
| 事务标识符低位 | 1字节 | 01 | 事务ID低8位,与请求相同,用于匹配响应 |
| 协议标识符高位 | 1字节 | 00 | 协议ID高8位 |
| 协议标识符低位 | 1字节 | 00 | 协议ID低8位,0x0000 |
| 长度高位 | 1字节 | 00 | 后续字节长度高8位 |
| 长度低位 | 1字节 | 07 | 后续字节长度低8位,组合0x0007=7字节(单元标识符1+功能码1+数据字节数1+寄存器数据4) |
| 单元标识符 | 1字节 | 01 | 原从站地址返回 |
| 功能码 | 1字节 | 03 | 原功能码返回 |
| 数据字节数 | 1字节 | 04 | 后续数据字节数,2个寄存器×2字节=4 |
| 寄存器1高位 | 1字节 | 01 | 第1个寄存器值高8位 |
| 寄存器1低位 | 1字节 | 02 | 第1个寄存器值低8位,组合0x0102=258 |
| 寄存器2高位 | 1字节 | 03 | 第2个寄存器值高8位 |
| 寄存器2低位 | 1字节 | 04 | 第2个寄存器值低8位,组合0x0304=772 |
其余功能码不过多阐述,原理参考RTU。







