Modbus协议简介与常用测试指令说明

Date Author Version Note
2022.07.19 Dog Tao V1.0 1. 完成了文档的撰写。
2023.08.04 Dog Tao V1.2 1. 修订文档,增加了Modbus协议简介小节。

本文档提供ModbusPoll调试软件与官方部署文档合辑资源(CSDN平台)。

文章目录

Modbus协议简介

发展历史

Modbus是一种通信协议,广泛用于工业控制系统之间的通信。它由Modicon(现在的施耐德电气)于1979年开发,用于与其PLC(可编程逻辑控制器)进行通信。Modbus协议主要有两个版本:Modbus RTU和Modbus TCP/IP。

  1. Modbus RTU:Modbus RTU是一种串行通信协议,通常在RS-485串行接口上运行。它是二进制协议,数据在总线上以连续字节的形式传输。每条消息都以设备地址开始,由功能代码(指示操作类型)和数据字节(包含操作数据)组成,并以两字节的循环冗余校验(CRC)结束,用于检测消息传输中的错误。

  2. Modbus TCP/IP:Modbus TCP/IP是基于以太网的Modbus协议版本。它在Modbus RTU的基础上增加了MBAP(Modbus Application Protocol)头部,以在TCP/IP网络上提供设备寻址和错误检测。Modbus TCP/IP通常在502端口上运行。

主要技术说明

  • 寻址:在Modbus协议中,每个设备都有一个唯一的地址。在RS-485网络中,地址范围是0-247。地址0是广播地址,发送到此地址的消息将被网络上的所有设备接收。

  • 寄存器:Modbus设备包含四种类型的寄存器:离散输入(只读)、线圈(可读写)、输入寄存器(只读)和保持寄存器(可读写)。每个寄存器都有一个唯一的地址,用于从设备读取或向设备写入数据。

  • 功能代码:Modbus协议定义了一组功能代码,用于指示要执行的操作,如读取寄存器(功能代码03或04)或写入寄存器(功能代码06或16)。如果设备不能执行请求的操作,它将返回一个异常响应,包含一个错误码。

  • 消息格式:Modbus消息由地址、功能码、数据和错误检查部分组成。在Modbus RTU中,错误检查通过CRC实现,而在Modbus TCP/IP中,通过MBAP头部的协议标识符和长度字段实现。

Modbus协议是一种简单、开放的协议,广泛用于工业自动化和嵌入式系统应用。尽管它已经存在了几十年,但由于其稳定性和易用性,它仍然是工业通信的主要标准之一。

基本规范与功能码

Modbus寄存器地址规则

Modbus协议定义的寄存器地址是5位十进制地址,即:

  • 线圈寄存器(Coils Register)地址:00001~09999
  • 离散寄存器(Discrete Register)地址:10001~19999
  • 输入寄存器(Input Register)地址:30001~39999
  • 保持寄存器(Holding Register)地址:40001~49999

由于上述各类地址是唯一对应的,因此有些资料就以其第一个数字区分各类地址 ,即:++0x代表线圈寄存器(CR)类地址,1x代表离散寄存器(DR)类地址、 3x代表输入寄存器(IR)类地址、4x代表保持寄存器(HR)类地址++。

在实际编程中,由于前缀的区分作用,所以只需说明后4位数,而且需转换为4位十六进制地址。

Modbus RTU报文基本格式

间隔 目标站号 功能码 数据 CRC16校验
起始应有不小于3.5个字符的报文间隔 1字节 1字节 n字节 2字节

下面对于各请求命令的"应答格式"的描述是指命令被正确执行时的应答格式。若CPU接收到错误的命令或者命令被执行错误,则返回的应答帧中"功能码"部分变为如下数据:功能码的最高位置1后得到的数据。比如功能码为01,若响应错误,则返回的功能码为0x81。

功能码01:读线圈寄存器(开关量输出)

  • 请求格式:
目标站号 功能码 起始地址 高字节 起始地址 低字节 读取个数 高字节 读取个数 低字节 CRC
1字节 01 1字节 1字节 1字节 1字节 2字节
  • 正确应答格式:
站号 功能码 返回数据字节数 返回数据字节1 返回数据字节2 ... CRC
1字节 01 1字节 1字节 1字节 ... 2字节

功能码02:读离散寄存器(开关量输入)

  • 请求格式:
目标站号 功能码 起始地址 高字节 起始地址 低字节 读取个数 高字节 读取个数 低字节 CRC
1字节 02 1字节 1字节 1字节 1字节 2字节
  • 正确应答格式:
站号 功能码 返回数据字节数 返回数据字节1 返回数据字节2 ... CRC
1字节 02 1字节 1字节 1字节 ... 2字节

功能码03:读保持寄存器(模拟量输出)

  • 请求格式:
目标站号 功能码 起始地址 高字节 起始地址 低字节 读取个数 高字节 读取个数 低字节 CRC
1字节 03 1字节 1字节 1字节 1字节 2字节
  • 正确应答格式:
站号 功能码 返回数据字节数 寄存器1高字节 寄存器1低字节 ... CRC
1字节 03 1字节 1字节 1字节 ... 2字节

功能码04:读输入寄存器(模拟量输入)

  • 请求格式:
目标站号 功能码 起始地址 高字节 起始地址 低字节 读取个数 高字节 读取个数 低字节 CRC
1字节 04 1字节 1字节 1字节 1字节 2字节
  • 正确应答格式:
站号 功能码 返回数据字节数 寄存器1高字节 寄存器1低字节 ... CRC
1字节 04 1字节 1字节 1字节 ... 2字节

功能码05:写单线圈(开关量输出)

  • 请求格式:
目标站号 功能码 线圈地址 高字节 线圈地址 低字节 强制值 高字节 强制值 低字节 CRC校验码
1字节 05 1字节 1字节 1字节 1字节 2字节

注:强制值= 0xFF00,则置线圈为ON;强制值=0x0000,则置线圈为OFF。

  • 应答格式:若设置成功,原文返回

功能码06:写单保持寄存器(模拟量输出)

  • 请求格式:
目标站号 功能码 寄存器地址 高字节 寄存器地址 低字节 强制值 高字节 强制值 低字节 CRC校验码
1字节 06 1字节 1字节 1字节 1字节 2字节
  • 应答格式:若设置成功,原文返回

功能码15 (0x0F):写多线圈(开关量输出)

  • 请求格式:
目标 站号 功能码 起始地址 高字节 起始地址低字节 数量 高字节 数量 低字节 强制值字节数 强制值 第1字节 ... CRC
1字节 15 1字节 1字节 1字节 1字节 1字节 1字节 ... 2字节
  • 正确应答格式:
目标站号 功能码 起始地址 高字节 起始地址低字节 数量 高字节 数量 低字节 CRC校验码
1字节 15 1字节 1字节 1字节 1字节 2字节

功能码16 (0x10):写多保持寄存器(模拟量输出)

  • 请求格式:
目标 站号 功能码 起始地址 高字节 起始地址低字节 数量 高字节 数量 低字节 强制值字节数 强制值1 高字节 强制值1 低字节 ... CRC
1字节 16 1字节 1字节 1字节 1字节 1字节 1字节 1字节 ... 2字节
  • 正确应答格式:
目标站号 功能码 起始地址 高字节 起始地址低字节 数量 高字节 数量 低字节 CRC 校验码
1字节 16 1字节 1字节 1字节 1字节 2字节

读寄存器测试指令

线圈寄存器-读命令(0x01)

从机地址 寄存器地址 寄存器数量 网络指令 modbus指令 说明 参考回复
0x01 0x999 0x02 00 32 17 01 01 03 E7 00 01 4D B9 读取输入寄存器第一个位值 01 01 01 00 51 88
0x01 0x999 0x02 00 32 17 01 01 03 E7 00 02 0D B8 读取输入寄存器前二个位值
0x01 0x999 0x02 00 32 17 01 01 03 E7 00 04 8D BA 读取输入寄存器前四个位值
0x01 0x999 0x02 00 32 17 01 01 03 E7 00 08 8D BF 读取输入寄存器前八个位值

离散寄存器-读命令(0x02)

从机地址 寄存器地址 寄存器数量 网络指令 modbus指令 说明
0x01 0x999 0x02 00 32 17 01 02 03 E7 00 01 09 B9 读取输入寄存器第一个位值
0x01 0x999 0x02 00 32 17 01 02 03 E7 00 02 49 B8 读取输入寄存器前二个位值
0x01 0x999 0x02 00 32 17 01 02 03 E7 00 04 C9 BA 读取输入寄存器前四个位值
0x01 0x999 0x02 00 32 17 01 02 03 E7 00 08 C9 BF 读取输入寄存器前八个位值

保持寄存器-读命令(0x03)

从机地址 寄存器地址 寄存器数量 网络指令 modbus指令 说明
0x01 0x999 0x02 00 32 17 01 03 03 E7 00 02 74 78 读取输入寄存器第一个32位数值(浮点数)
0x01 0x999 0x02 00 32 17 01 03 03 E7 00 04 F4 7A 读取输入寄存器前二个32位数值(浮点数)
0x01 0x999 0x02 00 32 17 01 03 03 E7 00 08 F4 7F 读取输入寄存器前四个32位数值(浮点数)
0x01 0x999 0x02 00 32 17 01 03 03 E7 00 10 F4 75 读取输入寄存器前八个32位数值(浮点数)

输入寄存器-读命令(0x04)

从机地址 寄存器地址 寄存器数量 网络指令 modbus指令 说明
0x01 0x999 0x02 00 32 17 01 04 03 E7 00 02 C1 B8 读取输入寄存器第一个32位数值(浮点数)
0x01 0x999 0x02 00 32 17 01 04 03 E7 00 04 41 BA 读取输入寄存器前二个32位数值(浮点数)
0x01 0x999 0x02 00 32 17 01 04 03 E7 00 08 41 BF 读取输入寄存器前四个32位数值(浮点数)
0x01 0x999 0x02 00 32 17 01 04 03 E7 00 10 41 B5 读取输入寄存器前八个32位数值(浮点数)
相关推荐
k093313 分钟前
sourceTree回滚版本到某次提交
开发语言·前端·javascript
神奇夜光杯21 分钟前
Python酷库之旅-第三方库Pandas(202)
开发语言·人工智能·python·excel·pandas·标准库及第三方库·学习与成长
Themberfue23 分钟前
Java多线程详解⑤(全程干货!!!)线程安全问题 || 锁 || synchronized
java·开发语言·线程·多线程·synchronized·
plmm烟酒僧25 分钟前
Windows下QT调用MinGW编译的OpenCV
开发语言·windows·qt·opencv
测试界的酸菜鱼36 分钟前
Python 大数据展示屏实例
大数据·开发语言·python
我是谁??36 分钟前
C/C++使用AddressSanitizer检测内存错误
c语言·c++
晨曦_子画1 小时前
编程语言之战:AI 之后的 Kotlin 与 Java
android·java·开发语言·人工智能·kotlin
Black_Friend1 小时前
关于在VS中使用Qt不同版本报错的问题
开发语言·qt
发霉的闲鱼1 小时前
MFC 重写了listControl类(类名为A),并把双击事件的处理函数定义在A中,主窗口如何接收表格是否被双击
c++·mfc
小c君tt1 小时前
MFC中Excel的导入以及使用步骤
c++·excel·mfc