MODBUS RTU/TCP协议及常用功能码详解

一、简介

ModBus是Modicon公司为其PLC通讯而开发的一种通讯协议。如今Modicon公司已经被施耐德收购成为了施耐德旗下品牌。从1979年问世至今,已经成为工业通讯领域的业界标准。
ModBus具有两种串行传输模式,ASCII 和 RTU。它们定义了数据如何打包、解码的不同方式。支持 Modbus 协议的设备一般都支持 RTU 格式。通信双方必须同时支持上述模式中的一种。

二、寄存器类型

MODBUS寄存器分类

寄存器种类 读写状态 数据类型 功能码 PLC地址
线圈寄存器 读/写 位(bit) 01H(读单/多个位); 05H(写单个位); 0FH(写多个位) 00001-09999
离散输入寄存器 只读 位(bit) 02H (读单/多个位) 10001-19999
保持寄存器 读/写 字(byte) 03H(读); 06H(写单个字节); 0FH(写多个字节) 30001-39999
输入寄存器 只读 字(byte) 04H (读单/多个字) 40001-49999

线圈寄存器:实际上可以表示一个开关量,线圈操作位(bit)一个bit对应一个开关信号,即(0/false,1/true),每个byte字节就能代表8个的位的开关信号,线圈寄存器支持读和写,Modbus的功能码又能对线圈的单个或多个进行一个读取写入操作,其实就是在操作字节的位。实对应上面的功能码也就是:0x01 0x05 0x0f

离散输入寄存器:离散输入寄存器就相当于线圈寄存器的只读模式,功能跟上面基本一致,除了不能写入。所以功能码也简单就一个读的 0x02

保持寄存器:保持寄存器是对字节进行的操作,每两个字节对应一个寄存器,支持读取和写入。功能码有对应的三个:0x03 0x06 0x10

输入寄存器:,这个和保持寄存器类似,但是也是只支持读而不能写。一个寄存器地址是占据两个byte的空间,也就是16个位。对应的功能码也就一个 0x04

言外之话:
当需要对保持寄存器操作时,不同的数据类型占据的字节长度其实是不一致的,一个寄存器地址占两个字节16位代表的只是一个单精度的数据。如C#的数据类型占据的长度如下
MODBUS RTU/TCP协议及常用功能码详解_第1张图片
C# 数据类型和字节长度
所以在读取写入保持寄存器的时候不同类型需要读取不同长度的字节才能拿到对应类型的值,写入的时候同理。如(int类型读取2个数量为int的时候需要乘以2,也就是读取4个寄存器才能拿到两个int类型的数据

三、MODBUS常用功能码

功能码 名称 操作数据类型 作用描述 PLC地址
01H 读线圈寄存器 位(bit) 获得一组开关线圈的当前状态(ON/OFF ) 00001-09999
02H 读离散输入寄存器 位(bit) 获得一组开关线圈的当前状态(ON/OFF ) 10001-19999
03H 读保持寄存器 字(byte) 在一个或多个保持寄存器中取得当前的二进制值 30001-39999
04H 读输入寄存器 字(byte) 在一个或多个输入寄存器中取得当前的二进制值 40001-49999
05H 写单个线圈寄存器 位(bit) 设置一个单独的线圈状态(ON/OFF ) 00001-09999
06H 写单个保持寄存器 字(byte) 写单个保持寄存器,将两个字节写入到寄存器 40001-49999
0FH 写多个线圈寄存器 位(bit) 写多个线圈寄存器,可以设置多个bit开关状态 00001-09999
10H 写多个保持寄存器 字(byte) 写多个保持寄存器,将多个字节写入到寄存器 40001-49999

MODBUS通讯协议格式

读线圈寄存器——01H

从站发送读取格式:

从站地址 功能码 起始地址高位 起始地址低位 读取数量高位 读取数量低位 CRC高位 CRC低位
0x01 0x01 0x00 0x00 0x00 0x02 BD CB

主站返回读取格式:

从站地址 功能码 返回字节数 data1 CRC高位 CRC低位
0x01 0x01 0x01 0x00 51 88

解读:
发送格式:
从站地址:01
功能码:01
起始地址: 00 00
读取数量: 00 02
CRC校验:BD CB
接收格式:
从站地址:01
功能码:01
返回字节数: 01
Data数据: 00(一个byte有8个bit,读取两个bit返回会补成字节用一个byte返回读取两个bit就行)
CRC校验:BD CB

读离散输入状态——02H

从站发送读取格式:

从站地址 功能码 起始地址高位 起始地址低位 读取数量高位 读取数量低位 CRC高位 CRC低位
0x01 0x02 0x00 0x00 0x00 0x02 F9 CB

主站返回读取格式:

从站地址 功能码 返回字节数 data1 CRC高位 CRC低位
0x01 0x02 0x01 0x00 A1 88

读保持寄存器——03H

从站发送读取格式:

从站地址 功能码 起始地址高位 起始地址低位 读取数量高位 读取数量低位 CRC高位 CRC低位
0x01 0x03 0x00 0x00 0x00 0x02 C4 CB

主站返回读取格式:

从站地址 功能码 返回字节数 data1 data2 data3 data4 CRC高位 CRC低位
0x01 0x03 0x04 0x00 0x0A 0x00 0x00 0A 31

解析读取返回:

为啥读取是读取两个地址数量会返回四个byte字节?因为在保持寄存器里面两个字节才对应一个寄存器,你读取两个寄存器地址数量就需要四个字节来表示。
注意:在解析字节的时候数据的高低位顺序倒序后才能表示一个数据

读输入寄存器——04H

同读取保存寄存器一样的格式,同上

写单个线圈——05H

从站地址 功能码 起始地址高位 起始地址低位 data1 data2 CRC高位 CRC低位
0x01 0x05 0x00 0x00 0xFF 0x00 8C 3A

主站返回读取格式:

从站地址 功能码 起始地址高位 起始地址低位 写入数据高位 写入数据低位 CRC高位 CRC低位
0x01 0x05 0x00 0x00 0xFF 0x00 8C 3A

解析:
写入无误的话返回同发送指令一样;通断标志为FF00H表示写ON,0000H表示写OFF,

写单个保持寄存器——06H

将地址0的保存寄存器的数据设置为10(单精度)
从站地址 功能码 起始地址高位 起始地址低位 data1 data2 CRC高位 CRC低位
0x01 0x06 0x00 0x00 0x00 0x0A 09 CD

主站返回读取格式:
响应:同发送指令;

写多个线圈——0FH

从站地址 功能码 起始地址高位 起始地址低位 写入数量高位 写入数据低位 字节长度 data1 CRC高位 CRC低位
0x01 0x0F 0x00 0x00 0x00 0x02 0x01 0x03 9E 96

主站返回读取格式:
响应:

从站地址 功能码 起始地址高位 起始地址低位 写入数量高位 写入数据低位 CRC高位 CRC低位
0x01 0x0F 0x00 0x00 0x00 0x02 9E 96

返回数据格式不返回Data数据

详情:写入数量为2的线圈,其中data1数据0x03代表0000 0011 将连续两个线圈置为ON

写多个保持寄存器——10H

从站地址 功能码 起始地址高位 起始地址低位 写入数量高位 写入数据低位 字节长度 data1 data2 data3 data4 CRC高位 CRC低位
0x01 0x10 0x00 0x00 0x00 0x02 0x04 0x0C 0x02 0x12 0x45 9C 6C

主站返回读取格式:
响应:

从站地址 功能码 起始地址高位 起始地址低位 写入数量高位 写入数据低位 CRC高位 CRC低位
0x01 0x10 0x00 0x00 0x00 0x02 41 CB

返回数据格式不返回Data数据

详情:写入数量为2的线圈,其中data1,data2,data3,data4数据两个代表一个单精度数据
0C 02表示一个3074 ,12 45代表一个4677

MODBUS TCP通讯协议格式

ModbusTCP的数据帧可分为两部分:MBAP+PDU。

| 事务处理标识| 协议标识 | 字节长度 | 单元标识符 | 功能码 |起始地址H | 起始地址L |数量H | 数量L

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

事务处理标识: 可以理解为报文的序列号,一般每次通信之后就要加1以区别不同的通信数据报文。
协议标识符: 00 00表示ModbusTCP协议。
字节长度: 表示接下来的数据长度,单位为字节
单元标识符: 可以理解为设备地址。

TCP跟RTU的协议格式其实基本上是一致的,只是TCP增加了报文头MBAP,取消了RTU的从站地址跟CRC校验

你可能感兴趣的:(计算机通讯,modbus)