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

[复制链接]
查看93515 | 回复0 | 2024-5-17 08:56:38 | 显示全部楼层 |阅读模式
一、简介

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#的数据类型占据的长度如下



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低位
0x010x010x000x000x000x02BDCB

主站返回读取格式:
从站地址功能码返回字节数data1CRC高位CRC低位
0x010x010x010x005188

解读:
发送格式:
从站地址: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低位
0x010x020x000x000x000x02F9CB

主站返回读取格式:
从站地址功能码返回字节数data1CRC高位CRC低位
0x010x020x010x00A188
读保持寄存器——03H

从站发送读取格式:
从站地址功能码起始地址高位起始地址低位读取数量高位读取数量低位CRC高位CRC低位
0x010x030x000x000x000x02C4CB

主站返回读取格式:
从站地址功能码返回字节数data1data2data3data4CRC高位CRC低位
0x010x030x040x000x0A0x000x000A31

解析读取返回:

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

同读取保存寄存器一样的格式,同上
写单个线圈——05H

从站地址功能码起始地址高位起始地址低位data1data2CRC高位CRC低位
0x010x050x000x000xFF0x008C3A

主站返回读取格式:
从站地址功能码起始地址高位起始地址低位写入数据高位写入数据低位CRC高位CRC低位
0x010x050x000x000xFF0x008C3A

解析:
写入无误的话返回同发送指令一样;通断标志为FF00H表示写ON,0000H表示写OFF,
写单个保持寄存器——06H

将地址0的保存寄存器的数据设置为10(单精度)
从站地址功能码起始地址高位起始地址低位data1data2CRC高位CRC低位
0x010x060x000x000x000x0A09CD

主站返回读取格式:
响应:同发送指令;
写多个线圈——0FH

从站地址功能码起始地址高位起始地址低位写入数量高位写入数据低位字节长度data1CRC高位CRC低位
0x010x0F0x000x000x000x020x010x039E96

主站返回读取格式:
响应:
从站地址功能码起始地址高位起始地址低位写入数量高位写入数据低位CRC高位CRC低位
0x010x0F0x000x000x000x029E96

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

详情:写入数量为2的线圈,其中data1数据0x03代表0000 0011 将连续两个线圈置为ON
写多个保持寄存器——10H

从站地址功能码起始地址高位起始地址低位写入数量高位写入数据低位字节长度data1data2data3data4CRC高位CRC低位
0x010x100x000x000x000x020x040x0C0x020x120x459C6C

主站返回读取格式:
响应:
从站地址功能码起始地址高位起始地址低位写入数量高位写入数据低位CRC高位CRC低位
0x010x100x000x000x000x0241CB

返回数据格式不返回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校验

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册哦

x
您需要登录后才可以回帖 登录 | 注册哦

本版积分规则