关于Modbus RTU和TCP协议的一些简要笔记

Modbus简述

Modbus是一种应用层的报文传输协议:

  • RTU

  • ASCII

  • TCP

方面 Modbus RTU Modbus TCP
物理层/传输介质 RS-232 / RS-485(串口) 以太网(TCP/IP)
编码方式 二进制(紧凑) 二进制(与RTU相同,但封装不同)
帧结构 Slave ID + PDU + CRC MBAP Header (7字节) + PDU
错误校验 CRC-16 无(依赖TCP校验和)
最大从站数 247 受IP网络限制,几乎无限
并发性 单主多从(主站轮询) 多主多从(多客户端并发)
速度 通常9600~115200 bps 10/100/1000 Mbps,延迟更低
距离 RS-485最远1200m 以太网标准距离,或通过光纤/路由器无限扩展
抗干扰 需终端电阻、光电隔离 依赖网络质量,工业以太网需交换机优化
典型应用场景 现场设备密集、成本敏感、低速 集中监控、远程访问、与IT系统集成
安全性 物理隔离,基本无加密 暴露在网络中,易受攻击(建议加VPN/防火墙)

Modbus RTU通信协议:

Modbus RTU(Remote Terminal Unit)是一种在工业领域广泛使用的串行通信协议。它支持通过串行连接进行远程设备间的通讯,以实现数据交换。

1.1 数据格式

从站地址(设备编号) 功能码 数据 校验
1 byte 1 byte N byte 2 byte

1.2 存储区

  • 输出线圈 0
    • 00001-09999
  • 输入线圈 1
    • 10001-19999
  • 输出寄存器 4
    • 40001-49999
  • 输入寄存器 3
    • 30001-39999

存储区范围5位和6位 标准地址和扩展地址

1.3 功能码

读和写 功能码
读输出线圈(读线圈) 01
读输入线圈(读离散输入) 02
读输出寄存器(读保持寄存器) 03
读输入寄存器 04
写单个输出线圈(写单个线圈) 05
写单个输出寄存器(写单个保持寄存器) 06
写多个输出线圈(写多个线圈) 15
写多个输出寄存器(写多个保持寄存器) 16

1.4 报文收发

功能码 请求与响应 数据格式
01读线圈 请求(主站-从站) 从站地址(1byte) 功能码(1byte) 线圈起始地址(2byte) 线圈数量(2byte) CRC校验码(2byte)
01读线圈 响应(从站-主站) 从站地址(1byte) 功能码(1byte) 字节数(1byte) 线圈值(nbyte) CRC校验码(2byte)
02读离散输入 请求(主站-从站) 从站地址(1byte) 功能码(1byte) 离散输入起始地址(2byte) 离散输入数量(2byte) CRC校验码(2byte)
02读离散输入 响应(从站-主站) 从站地址(1byte) 功能码(1byte) 字节数(1byte) 离散输入值(nbyte) CRC校验码(2byte)
03读保持寄存器 请求(主站-从站) 从站地址(1byte) 功能码(1byte) 保持寄存器起始地址(2byte) 保持寄存器数量(2byte) CRC校验码(2byte)
03读保持寄存器 响应(从站-主站) 从站地址(1byte) 功能码(1byte) 字节数(1byte) 保持寄存器值(nbyte) CRC校验码(2byte)
04读输入寄存器 请求(主站-从站) 从站地址(1byte) 功能码(1byte) 输入寄存器起始地址(2byte) 输入寄存器数量(2byte) CRC校验码(2byte)
04读输入寄存器 响应(从站-主站) 从站地址(1byte) 功能码(1byte) 字节数(1byte) 输入寄存器值(nbyte) CRC校验码(2byte)
05写单个线圈 请求(主站-从站) 从站地址(1byte) 功能码(1byte) 线圈地址(2byte) 线圈写入值(2byte) CRC校验码(2byte)
05写单个线圈 响应(从站-主站) 从站地址(1byte) 功能码(1byte) 线圈地址(2byte) 线圈写入值(2byte) CRC校验码(2byte)
06写单个保持寄存器 请求(主站-从站) 从站地址(1byte) 功能码(1byte) 寄存器地址(2byte) 寄存器写入值(2byte) CRC校验码(2byte)
06写单个保持寄存器 响应(从站-主站) 从站地址(1byte) 功能码(1byte) 寄存器地址(2byte) 寄存器写入值(2byte) CRC校验码(2byte)
15写多个线圈 请求(主站-从站) 从站地址(1byte) 功能码(1byte) 线圈起始地址(2byte) 线圈数量(2byte) 字节数(1byte) 线圈写入值(nbyte) CRC校验码(2byte)
15写多个线圈 响应(从站-主站) 从站地址(1byte) 功能码(1byte) 线圈起始地址(2byte) 线圈数量(2byte) CRC校验码(2byte)
16写多个保持寄存器 请求(主站-从站) 从站地址(1byte) 功能码(1byte) 保持寄存器起始地址(2byte) 保持寄存器数量(2byte) 字节数(1byte) 保持寄存器写入值(nbyte) CRC校验码(2byte)
16写多个保持寄存器 响应(从站-主站) 从站地址(1byte) 功能码(1byte) 保持寄存器起始地址(2byte) 保持寄存器数量(2byte) CRC校验码(2byte)

1.5 代码示例

发送:01 03 00 00 00 02 C4 0B

接收:01 03 04 01 46 01 3B 5A 59

发送报文 解析 接收报文 解析
01 站地址 01 站地址
03 读输出寄存器 03 读输出寄存器
00 00 起始寄存器 04 字节计数
00 02 寄存器长度 01 46 01 3B 具体四个字节
C4 0B CRC校验 5A 59 CRC校验

Modbus TCP通信协议:

2.1 数据格式

事务处理标识 协议标识 长度 单元标识 功能码 起始地址 数据
2字节 2字节 2字节 1字节 1字节 2字节 N字节

2.2 Modbus 地址映射到 CPU 地址

Modbus地址 CPU地址
00001 Q0.0
00002 Q0.1
...... ......
10001 I0.0
10002 I0.1
...... ......
30001 AIW0
30002 AIW2
...... ......
40001 Vx(保持寄存器起始地址)例:VW0
40002 Vx+2 =(保持寄存器起始地址+2)例:VW2
...... ......

2.3 报文头(MBAP头)及功能码

其中,事务处理标识、协议标识符、长度和单元标识符统称为报文头(MBAP头)。

内容 解释
事务处理标识 可以理解为报文序列号,一般每次通信后就要加1,以区分不同的通信数据报文。
协议标识符 00 00 表示Modbus TCP 协议
长度 接下来数据长度,单位字节
单元标识符 设备地址,一般为01 00 FF
功能码 描述 说明 MOUBUS地址
01(0x01) 读离散输出寄存器(读线圈(Coils)) 位操作 00001 ~ 09999
02(0x02) 读离散输入寄存器 位操作 10001 ~ 19999
03(0x03) 读保持寄存器(最常用) 字操作 40001 ~ 49999
04(0x04) 读输入寄存器 字操作 30001 ~ 39999
05(0x05) 写离散输出寄存器(写单个线圈) 位操作 00001 ~ 09999
06(0x06) 写保持寄存器(写单个寄存器) 字操作 40001 ~ 49999
15(0x0F) 写多线圈寄存器(写多个线圈) 位操作 00001 ~ 09999
16(0x10) 写多个保持寄存器(写多个寄存器) 字操作 40001 ~ 49999

2.4 报文收发

功能码 请求与响应 数据格式
01读线圈 请求(主站-从站) 事务处理标识符(2byte) 协议标识符(2byte) 长度(2byte) 单位标识符(1byte) 功能码(1byte) 线圈起始地址(2byte) 线圈数量(2byte)
01读线圈 响应(从站-主站) 事务处理标识符(2byte) 协议标识符(2byte) 长度(2byte) 单位标识符(1byte) 功能码(1byte) 字节数(1byte) 线圈值(nbyte)
02读离散输入 请求(主站-从站) 事务处理标识符(2byte) 协议标识符(2byte) 长度(2byte) 单位标识符(1byte) 功能码(1byte) 离散输入起始地址(2byte) 离散输入数量(2byte)
02读离散输入 响应(从站-主站) 事务处理标识符(2byte) 协议标识符(2byte) 长度(2byte) 单位标识符(1byte) 功能码(1byte) 字节数(1byte) 离散输入值(nbyte)
03读保持寄存器 请求(主站-从站) 事务处理标识符(2byte) 协议标识符(2byte) 长度(2byte) 单位标识符(1byte) 功能码(1byte) 保持寄存器起始地址(2byte) 保持寄存器数量(2byte)
03读保持寄存器 响应(从站-主站) 事务处理标识符(2byte) 协议标识符(2byte) 长度(2byte) 单位标识符(1byte) 功能码(1byte) 字节数(1byte) 保持寄存器值(nbyte)
04读输入寄存器 请求(主站-从站) 事务处理标识符(2byte) 协议标识符(2byte) 长度(2byte) 单位标识符(1byte) 功能码(1byte) 输入寄存器起始地址(2byte) 输入寄存器数量(2byte)
04读输入寄存器 响应(从站-主站) 事务处理标识符(2byte) 协议标识符(2byte) 长度(2byte) 单位标识符(1byte) 功能码(1byte) 字节数(1byte) 输入寄存器值(nbyte)
05写单个线圈 请求(主站-从站) 事务处理标识符(2byte) 协议标识符(2byte) 长度(2byte) 单位标识符(1byte) 功能码(1byte) 线圈地址(2byte) 线圈写入值(2byte)
05写单个线圈 响应(从站-主站) 事务处理标识符(2byte) 协议标识符(2byte) 长度(2byte) 单位标识符(1byte) 功能码(1byte) 线圈地址(2byte) 线圈写入值(2byte)
06写单个保持寄存器 请求(主站-从站) 事务处理标识符(2byte) 协议标识符(2byte) 长度(2byte) 单位标识符(1byte) 功能码(1byte) 寄存器地址(2byte) 寄存器写入值(2byte)
06写单个保持寄存器 响应(从站-主站) 事务处理标识符(2byte) 协议标识符(2byte) 长度(2byte) 单位标识符(1byte) 功能码(1byte) 寄存器地址(2byte) 寄存器写入值(2byte)
15写多个线圈 请求(主站-从站) 事务处理标识符(2byte) 协议标识符(2byte) 长度(2byte) 单位标识符(1byte) 功能码(1byte) 线圈起始地址(2byte) 线圈数量(2byte) 字节数(1byte) 线圈写入值(nbyte)
15写多个线圈 响应(从站-主站) 事务处理标识符(2byte) 协议标识符(2byte) 长度(2byte) 单位标识符(1byte) 功能码(1byte) 线圈起始地址(2byte) 线圈数量(2byte)
16写多个保持寄存器 请求(主站-从站) 事务处理标识符(2byte) 协议标识符(2byte) 长度(2byte) 单位标识符(1byte) 功能码(1byte) 保持寄存器起始地址(2byte) 保持寄存器数量(2byte) 字节数(1byte) 保持寄存器写入值(nbyte)
16写多个保持寄存器 响应(从站-主站) 事务处理标识符(2byte) 协议标识符(2byte) 长度(2byte) 单位标识符(1byte) 功能码(1byte) 保持寄存器起始地址(2byte) 保持寄存器数量(2byte)

2.5 代码示例

示例1: 读取保持寄存器,功能码0x03
result = client.read_holding_registers(0, count=2, slave=1)

address: int,寄存器地址,开始读取的地址,依据从机设置的地址配置

功能码:03已默认

count: 要读取的寄存器数量

slave: 与从机匹配

发送:00 01 00 00 00 06 01 03 00 00 00 02

接收:00 01 00 00 00 07 01 03 04 00 0A 00 64

发送报文 解析 接收报文 解析
00 01 事务ID 00 01 事务ID
00 00 协议ID 00 00 协议ID
00 06 后续6字节 00 07 后续7字节
01 单位标识符 01 单位标识符
03 功能码:读输出寄存器 03 功能码:读输出寄存器
00 00 保持寄存器起始地址 04 字节计数
00 02 保持寄存器长度 00 0A 00 64 具体四个字节

Modbus TCP 通讯数据示例

3.1 功能码01 读离散输出线圈

事务处理标识 协议标识 长度 单元标识 功能码 起始地址 数据长度
00 11 00 00 00 06 01 01 00 00 00 08

注释:读取Q0.0地址开始的8个连续输出点(即Q0.0-Q0.7)。

3.2 功能码02 读离散输入线圈

事务处理标识 协议标识 长度 单元标识 功能码 起始地址 数据长度
00 15 00 00 00 06 01 02 00 00 00 08

注释:读取I0.0地址开始的8个连续输出点(即I0.0-I0.7)。

3.3 功能码03 读保持寄存器

事务处理标识 协议标识 长度 单元标识 功能码 起始地址 数据长度
00 66 00 00 00 06 01 03 00 00 00 02

注释:读取VW0地址开始的2个连续字空间(即vw0,vw2)。

3.4 功能码04 读输入寄存器

事务处理标识 协议标识 长度 单元标识 功能码 起始地址 数据长度
00 97 00 00 00 06 01 04 00 00 00 02

注释:读取AIW0地址开始的2个连续字空间(即AIW0,AIW2)。

3.5 功能码05 写单个离散输出寄存器

事务处理标识 协议标识 长度 单元标识 功能码 起始地址 数据长度
00 C2 00 00 00 06 01 05 00 00 FF 00

注释:将地址00000的输出离散线圈置一(即让Q0.0置一)。

事务处理标识 协议标识 长度 单元标识 功能码 起始地址 数据长度
01 0A 00 00 00 06 01 05 00 01 00 00

注释:将地址00001的输出离散线圈置一(即让Q0.1复位)。

3.6 功能码06 写单个保持寄存器

事务处理标识 协议标识 长度 单元标识 功能码 起始地址 数据长度
01 5e 00 00 00 06 01 06 00 02 00 7b

注释:往地址VW4寄存器中写入数值0x007B(即十进制数123)。

3.7 功能码15 写多个线圈寄存器

事务处理标识 协议标识 长度 单元标识 功能码 起始地址 数据长度(位) 字节数 数据
01 5e 00 00 00 09 01 0F 00 00 00 10 02 aa cb

注释:往地址QB0寄存器中写入数值0xaa,往地址QB1寄存器中写入数值0xcb。

数据长度位不满8的N倍,字节数也算N个。

3.8 功能码16 写多个保持寄存器

事务处理标识 协议标识 长度 单元标识 功能码 起始地址 数据长度(位) 字节数 数据
02 68 00 00 00 0B 01 10 00 00 00 02 04 00 7B 00 EA

注释:往地址VW0寄存器中写入数值0x007B,往地址VW2寄存器中写入数值0x00EA。

配置ModBus TCP连接通常涉及以下几个步骤:

  • 确定网络参数 :获取目标设备的IP地址和端口号。
  • 安装ModBus TCP客户端软件 :选择合适的ModBus客户端软件,如Modscan、MBConnectLine等。
  • 配置连接参数 :在客户端软件中设置目标设备的IP地址和端口,确认连接的超时时间。
  • 选择通信模式 :选择TCP作为通信模式。
  • 连接测试 :尝试连接到设备,如果连接成功,配置完成。
  1. 启动MBConnectLine
  2. 点击"File" -> "New Project"
  3. 选择"Modbus TCP"
  4. 输入设备的IP地址和端口(例如:192.168.1.101:502)
  5. 点击"Connect"测试连接
  6. 查看状态栏,显示"Connected"表示配置成功。
相关推荐
不懂的浪漫5 小时前
Netty 不只是 TCP 框架:它解决的是高并发业务系统的组织问题
网络·网络协议·tcp/ip·架构·netty
求学中--7 小时前
数据持久化与网络请求全攻略:Preferences、关系数据库、HTTP实战
网络·网络协议·http
想成为优秀工程师的爸爸7 小时前
车载以太网之要火系列 - 第35篇:郭大侠学UDS(34/36/37服务)- 环环相扣展神奇,丝滑更新不迷离
网络协议·uds·车载以太网
IPDEEP全球代理8 小时前
美国原生IP是什么意思?有什么用?
网络·网络协议·tcp/ip
techdashen8 小时前
Cloudflare 开源 h3i:深入 HTTP/3 协议调试的利器
网络协议·http·开源
计算机安禾9 小时前
【计算机网络】第18篇:UDP的轻量级设计——无连接传输的本质及QUIC的改造路径
网络协议·计算机网络·udp
TYKJ0239 小时前
Day3、我在生产环境踩过的5个网络配置坑(每一个都差点背锅)
网络协议·敏捷开发
S1998_1997111609•X10 小时前
元组件HCG&&单元量泄露数据爬虫植入syatem,造成系统ioc dark and agent of China gov 的犯罪心理学依据行为
网络协议·安全·百度·哈希算法·开闭原则
roman_日积跬步-终至千里11 小时前
TCP vs Thrift:底层传输 vs 完整RPC框架的核心区别
网络协议·tcp/ip·rpc