郗燕岚 发表于 2026-2-2 23:20:02

Modbus 协议 学习一则

Modbus 协议

一文学习 了解 OSI模型、TCP/IP模型、网络封包
Modbus 是一种通信协议,用于在工业自动化领域中的设备之间进行数据交换。它是一种简单而广泛使用的串行通信协议,用于将控制设备(如传感器、执行器、PLC等)与监控设备(如计算机、远程终端等)连接起来。
Modbus RTU、ASCII、TCP 的区别

Modbus的协议版本 包括Modbus RTU、Modbus ASCII、Modbus TCP/IP、Modbus UDP/IP等

[*]Modbus RTU与Modbus ASCII,都使用串口通讯协议,Modbus RTU使用二进制格式进行数据传输,通讯效率更高,Modbus ASCII使用ASCII码进行数据传输,可读性好,但通讯效率更低。
[*]Modbus TCP/IP是基于以太网的一种通讯方式,它将Modbus协议封装在TCP/IP协议栈中,通过以太网传输数据。具有高速、稳定的特点。
[*]Modbus UDP/IP是基于UDP/IP协议的一种通讯方式
Modbus RTU使用二进制编码进行通信,而Modbus ASCII则使用可打印的ASCII字符。Modbus RTU是更常用的版本,因为它在数据传输效率方面更高。
Modbus协议采用主从结构,其中一个设备充当主站(主机),负责发起通信请求和控制操作,而其他设备则充当从站(从机),接收主站的请求并提供数据。只能主站发起请求,从站不能,发起请求
Modbus 结构

​1. 数据传输格式

​协议类型​数据编码​帧结构​示例​RTU​二进制紧凑的二进制数据,直接传输十六进制字节(如 0x01)。​ASCII​ASCII字符数据转换为可读的ASCII字符(如 "0" → 0x30),每字节拆分为两个ASCII字符。:010300010001D5CA​TCP​二进制(基于TCP)​在TCP/IP协议栈上传输,添加MBAP头(Modbus Application Protocol header)。000100000006010300010001​2. 帧结构与分隔符

​协议类型​帧起始符​帧结束符​校验方式​字节间隔要求​RTU无无CRC(2字节)严格时间间隔(3.5字符)​ASCII:(冒号)CR+LF(回车换行)LRC(纵向冗余校验)无严格间隔要求​TCPMBAP头通过TCP包长度标识无额外校验(依赖TCP/IP校验)无间隔要求​3. 传输效率

​协议类型​效率​RTU​高:二进制编码,数据紧凑,适合低速串行链路(如RS-485)。​ASCII​低:每个字节需转换为2个ASCII字符(如0xA1→"A""1"),传输数据量翻倍。​TCP​高:基于TCP/IP,支持高速网络,但需额外添加MBAP头(7字节)。​4. 校验方式

​协议类型​校验机制​校验范围​RTU​CRC-16​(循环冗余校验)整个数据帧(地址+功能码+数据)​ASCII​LRC​(纵向冗余校验,1字节)数据字段(不包含起始/结束符)​TCP​依赖TCP/IP校验​(无额外Modbus层校验)TCP/IP协议栈自动校验

[*]RTU / CRC-16-IBM
CRC-16的算法有多种变种,Modbus使用的是CRC-16-IBM
以 0x01,0x03,0x00,0x00,0x00,0x08,0x44,0x0C的 0x3 请求为例 其中0x01,0x03,0x00,0x00,0x00,0x08 的CRC-16 (Modbus) 实际计算工具检验码是(0x440C)
按大端序输出​​:高字节 0x0C → 0x44
byte[] data = {0x01,0x03,0x00,0x00,0x00,0x08};crc-calculation - https://www.lammertbies.nl/comm/info/crc-calculation
​5. 物理接口

​协议类型​传输介质​典型速率​应用场景​RTURS-485/RS-2321.2kbps - 115.2kbps工业现场设备(PLC、传感器)​ASCIIRS-485/RS-232低于RTU(因效率低)调试场景(数据可读性强)​TCP以太网(TCP/IP)10Mbps - 1Gbps工厂局域网、SCADA系统远程通信数据帧格式

无论哪一种Modbus协议版本的帧格式都是一样的
数据帧部分描述占用字节设备地址(Slave ID)识别从站的唯一地址1字节功能码(Function Code)主机对从机实现的操作,功能码1字节数据区(Data Field)包含功能码所需的数据或返回的数据可变错误校验(CRC)循环冗余校验,用于错误检测2字节主站发出的功能码 01 ~ 06 的请求时, 数据一定的8个字节(数据区使用1个字节表示开始地址, 1个字节表示长度)
数据/地址类型

Modbus中定义的四种数据类型

[*]离散输出(Discrete Outputs):

[*]这些寄存器也称为线圈(Coils),它们代表二进制输出(0 或 1),通常用于控制开关设备。
[*]地址范围通常是 0x00001 到 0xFFFFF(Modbus TCP)或 0x0000 到 0xFFFF(Modbus RTU/ASCII)。
[*]功能码 01(读取线圈状态)和 05(写入单个线圈)用于离散输出。

[*]离散输入(Discrete Inputs):

[*]这些寄存器代表二进制输入状态,它们是只读的,通常用于表示传感器或开关的状态。
[*]地址范围通常是 0x10001 到 0x1FFFF(Modbus TCP)或 0x0001 到 0xFFFF(Modbus RTU/ASCII)。
[*]功能码 02(读取离散输入状态)用于离散输入。

[*]保持寄存器(Holding Registers):

[*]这些寄存器用于存储可读写的数值数据,通常用于表示过程变量,如温度或压力。
[*]地址范围通常是 0x40001 到 0x4FFFF(Modbus TCP)或 0x0000 到 0xFFFF(Modbus RTU/ASCII)。
[*]功能码 03(读取保持寄存器)和 06(写入单个保持寄存器)用于保持寄存器。

[*]输入寄存器(Input Registers):

[*]这些寄存器用于存储只读数值数据,通常用于表示模拟量输入,如电流或电压。
[*]地址范围通常是 0x30001 到 0x3FFFF(Modbus TCP)或 0x0000 到 0xFFFF(Modbus RTU/ASCII)。
[*]功能码 04(读取输入寄存器)用于输入寄存器。

功能码

​​功能码(十六进制)​​​​名称​​​​操作类型​​​​访问权限​​​​PLC 地址范围​​​​数据类型​​​​0x01​读取线圈状态(Read Coils)位操作读00001-09999(0x地址)二进制位(ON/OFF)​​0x02​​读取离散输入状态(Read Discrete Inputs)位操作读10001-19999(1x地址)二进制位(ON/OFF)​​0x03​​读取保持寄存器(Read Holding Registers)字操作读40001-49999(4x地址)16位整数/浮点数​​0x04​​读取输入寄存器(Read Input Registers)字操作读30001-39999(3x地址)16位整数/浮点数​​0x05​​写单个线圈(Write Single Coil)位操作写00001-09999(0x地址)二进制位(ON/OFF)​​0x06​​写单个保持寄存器(Write Single Register)字操作写40001-49999(4x地址)16位整数/浮点数​​0x0F​​写多个线圈(Write Multiple Coils)位操作写00001-09999(0x地址)二进制位(ON/OFF)​​0x10​​写多个保持寄存器(Write Multiple Registers)字操作写40001-49999(4x地址)16位整数/浮点数​​0x07​​读取异常状态(Read Exception Status)位操作读由设备定义(内部线圈)二进制位(ON/OFF)​​0x08​​回送诊断校验(Diagnostics)诊断操作读/写无特定地址诊断数据Modbus功能码占用一个字节,取值范围是1127(即0x010x7F)。同时,使用功能码+0x80表示异常状态,即129~255代表异常码。
在Modbus标准协议中,一共规定了三类Modbus功能码。

[*]公共功能码
。被明确定义的功能码;
。保证唯一性;
。由Modbus协会确认,并提供公开的文档:
。可进行一致性测试:
。包括协议定义的功能码和保留将来使用的功能码。
[*]用户自定义功能码
。有两个用户自定义功能码区域,分别是6572和100110;
。用户自定义,不保证唯一性。
[*]保留功能码
。保留功能码是因为历史遗留原因,某些公司的传统产品上现行使用的功能码不作为公共使用。
实际最常用的是公共功能码中的4个功能码:03/04/06/10
实例

主站发送

主站向从站发送的实际请求数据帧:03 04 00 08 00 01 B0 3B (假设从站地址为03)
其中:
03:为主站要访问的域名(即从站地址,范围0~247)。
04:表示功能码。
00 08:表示从从站寄存器08这个地址开始读取数据。
00 01:表示从站寄存器, 读取数据的长度。(这里即读取一个字节)
b0 3b:两个字节的校验数据。(Modbus CRC)
从站响应

从站接收到主站的请求数据帧之后实际的响应数据帧为:03 04 02 00 0A 40 F7
其中:
03:为从站地址即域名(即从站地址,范围0~247)。(主站发送什么就响应什么)
04:表示功能码。(主站发送什么就响应什么)
02:被读取数据长度(所以最多 255 - 4字节? 253字节)
00 0A:被读取的具体数据
40 F7:两个字节的校验数据
协议限制


[*]Modbus协议报文(两个帧的)间隔需要大于3.5个字符计算:
1.1、有检验位
1个字符=1(起始位)+8(数据位)+1(奇偶校验位)+1(停竖位)=11位3.5个字符=3.511=38.5位
如果波特率=9600bps,则3.5个字符间隔时间为 38.5/9.6=4.0104167ms : 字节间间隔时间=1.5字符间隔时间 ≈2.6042ms
1.2 无校验位
1个字符=1(起始位)+8(数据位)+0(无校验位)+1(停止位)=10位
3.5个字符=3.5*10=35位
如果波特率=9600bps,则3.5个字符间隔时间为35/9.6=3.6458毫秒
[*]通常可以将传输 45位的时间四舍五入后做为报文时间间隔。
如果波特率=9600bps,则45位传输时间为45/9.6=4.6875≈5毫秒

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

眸胝 发表于 2026-2-4 04:04:39

前排留名,哈哈哈

锺冰洁 发表于 2026-2-4 05:37:00

过来提前占个楼

盗衍 发表于 2026-2-8 04:42:31

东西不错很实用谢谢分享

谲脾 发表于 2026-2-8 04:52:09

这个好,看起来很实用

澹台忆然 发表于 2026-2-9 08:55:07

热心回复!

迎脾 发表于 2026-2-9 14:17:16

谢谢楼主提供!

靳夏萱 发表于 2026-2-9 22:38:29

感谢分享,下载保存了,貌似很强大

糙昧邵 发表于 2026-2-10 18:25:52

谢谢分享,试用一下

致掣 发表于 2026-2-12 10:04:39

热心回复!

郗新语 发表于 2026-2-20 04:09:49

感谢发布原创作品,程序园因你更精彩

匡菲 发表于 2026-2-22 07:23:35

分享、互助 让互联网精神温暖你我

轩辕娅童 发表于 2026-2-23 08:32:44

谢谢分享,试用一下

公西颖初 发表于 2026-2-24 04:53:05

这个有用。

劳暄美 发表于 2026-2-24 23:41:48

用心讨论,共获提升!

捐催制 发表于 2026-3-8 06:35:39

鼓励转贴优秀软件安全工具和文档!

庇床铍 发表于 2026-3-8 21:07:43

喜欢鼓捣这些软件,现在用得少,谢谢分享!

凶契帽 发表于 前天 20:24

分享、互助 让互联网精神温暖你我
页: [1]
查看完整版本: Modbus 协议 学习一则