Modbus规约格式分析与总结(数据帧示例超详细)
Modbus概述
Modbus通信协议由Modicon公司(现已经为施耐德公司并购,成为其旗下的子品牌)于1979年发明的,是全球最早用于工业现场的总线规约。由于其免费公开发行,使用该协议的厂家无需缴纳任何费用,Modbus通信协议采用的是主从通信模式(即Master/Slave通信模式),其在分散控制方面应用极其广泛,从而使得Modbus协议在全球得到了广泛的应用。
Modbus通信协议具有多个变种,其具有支持串口(主要是RS-485总线),以太网多个版本,其中最著名的是Modbus RTU,Modbus ASCII和Modbus TCP三种。其中Modbus RTU与Modbus ASCII均为支持RS-485总线的通信协议,其中Modbus RTU由于其采用二进制表现形式以及紧凑数据结构,通信效率较高,应用比较广泛。而Modbus ASCII由于采用ASCII码传输,并且利用特殊字符作为其字节的开始与结束标识,其传输效率要远远低于Modbus RTU协议,一般只有在通信数据量较小的情况下才考虑使用Modbus ASCII通信协议,在工业现场一般都是采用Modbus RTU协议,一般而言,大家说的基于串口通信的Modbus通信协议都是指Modbus RTU通信协议。
上面是百度百科对于modbus的解释,我理解的modbus,是一种工业上最为简洁的协议,能够很好的将实时数据从一个设备传输到它的采集器。当然它的优势也就只有简洁了,轮询的方式发送请求帧来请求数据,数据量稍微一大会造成实时数据很大的延时,因为一帧最多请求128个寄存器,还要考虑主站处理请求帧的延时,以及硬件线路延时等等,延时会更大。现在电力行业在数据采集上有更好的协议替代它,如104跟61850等都已经具备了主站变位主动上报的功能,这样就大大提高了数据采集的实时性。104跟61850后续再细说,本次重点关注modbus
Modbus协议名称解释
功能码:功能码在modbus协议用于表示信息帧的功能,常用的功能码有03,04,06,16等,其中03功能码的作用是读保持寄存器内容,04功能码的作用是读输入寄存器内容,06功能码的内容是写单个保持寄存器,16功能码的内容则是写多个保持寄存器。
输入寄存器和保持寄存器:04功能码的作用就是读输入寄存器,而03功能码的作用则是读保持寄存器,很多人在看到这两个功能码的时候总是希望找到这两个功能码的区别,保持寄存器和输入寄存器到底是什么区别,modbus协议最开始是用来解决PLC的通信协议问题的,主要用于输入输出数字量信号以及模拟量信号,所谓的输入寄存器就是从模拟量信号输入引申出来的,即输入寄存器只能从模拟量信号输入端改变寄存器,而主机则不能通过下发指令改变输入寄存器的数据,而保持寄存器则是用于输出模拟量信号的,主机是可以改变寄存器数据,也就是说对于主机而言,输入寄存器是只读的,而保持寄存器是可以读写的,当主机用06,16功能码的指令去预置输入寄存器的时候,设备会返回一个代码为0x81的错误代码,即企图写只读寄存器。
Modbus中的数据地址格式:在Modbus协议中,经常会出现类似于3xxxx,4xxxx寄存器,这个表示的是寄存器支持的数据类型。Modbus数据地址格式是从0开始,比如以下一个寄存器40009,即表示保持寄存器,寄存器地址为00 08,类似的数据地址格式经常在组态软件以及PLC系统中用到。
Modbus RTU/ASCII/TCP:Modbus协议最开始是用于可编程逻辑控制器(PLC)之间的通讯,由于其具有的开放性,大量的用于现场智能仪表。Modbus协议有多个变种,其中最著名的是Modbus RTU/Modbus ASCII和Modbus TCP通信协议。其中RTU/ASCII协议是基于串行口通信,而TCP协议则是基于以太网通信。
Modbus错误代码表:modbus有功能码,校验码,异常功能码和错误代码,其中异常功能码和错误代码非常容易混淆,一般来说异常功能码指的是某个功能码执行的时候出现的相应异常功能码,一般都是在功能码的基础上加上0x80,比如03功能码出现的异常码是0x83异常功能码,16功能码对应出现的异常功能码则是0x90,而错误代码则是表示出现错误的具体情况,比如寄存器地址不存在,不管是读还是写,如果该寄存器地址不存在的话,错误代码为02。
其中物理离散量输入和输入寄存器只能有I/O系统提供的数据类型,即只能是由I/O系统改变离散量输入和输入寄存器的数值,而上位机程序不能改变的数据类型,在数据读写上表现为只读,而内部比特或者物理线圈和内部寄存器或物理输出寄存器(保持寄存器)则是上位机应用程序可以改变的数据类型,在数据读写上表现为可读可写。
下发指令:01 10 01 8E 00 01 02 00 00 69 BE(向寄存器0x018E写入一个数值为0的数据)
正确回应指令:01 10 01 8E 00 01 60 1E(向寄存器地址0x018E写操作一个寄存器)
错误回应指令:01 90 01 8D C0(写操作非法功能,可能是向输入寄存器写数据)
注:异常功能码为在原来功能码的基础上机上80H,异常回复报文的主要内容就是错误码,不同错误码代表含义不同
Modbus RTU/TCP协议
Modbus TCP协议则是在RTU协议上加一个MBAP报文头,由于TCP是基于可靠连接的服务,RTU协议中的CRC校验码就不再需要,所以在Modbus TCP协议中是没有CRC校验码。
RTU数据格式:
主机请求消息
[03][03][00][00][00][0A][C4][2F]
Slave id(BIT0)
Function(BIT1)
addr(BIT2、BIT3)
nb(BIT4、BIT5) 请求的数据大小
CRC(BIT6、BIT7)
从机回复消息
03 03 14 00 01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00 09 00 0A 16 6F
Slave id(BIT0)
Function(BIT1)
nb(BIT2) 回复的数据大小,是请求数据大小的两倍,每个数据占两个自己
data(BIT3-BIT22)
CRC(BIT23、BIT24)
TCP数据格式:
主机请求消息
07 78 00 00 00 06 03 03 00 00 00 14
事务处理标识
2字节
07 78可以理解为报文的序列号,一般每次通信之后就要加1以区别不同的通信数据报文。
协议标识符
2字节
00 00表示ModbusTCP协议。
长度
2字节
00 06表示接下来的数据长度,单位为字节。
单元标识符
1字节
03可以理解为Slave设备地址。
功能码
1字节
03 功能码,读保持寄存器
起始地址
2字节
00 00 起始地址
寄存器数量
2字节
00 14 读取寄存器数量
从机回复消息
07 78 00 00 00 2B 03 03 28 00 01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00 09 00 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
事务处理标识
2字节
07 78可以理解为报文的序列号,一般每次通信之后就要加1以区别不同的通信数据报文。
协议标识符
2字节
00 00表示ModbusTCP协议。
长度
2字节
00 2B表示接下来的数据长度,单位为字节。
单元标识符
1字节
03可以理解为Slave设备地址。
功能码
1字节
03 功能码,读保持寄存器
起始地址
1字节
28 回复的数据大小
寄存器数据
xxx字节
读取的寄存器数据
下面针对每个功能码进行收发帧测试
功能码01的modbus RTU报文
注:采用小端对齐的方式,即数据的低位对应地址低位,数据的高位保存地址的高位
例子:
Tx:01 01 00 00 00 03 7C 0B
Rx:01 01 01 03 11 89
注:此处的03表示0000011
Tx:01 01 00 00 00 03 7C 0B
Rx:01 01 01 07 10 4A
功能码为02 的modbus RTU报文
Rx:01 02 01 07 E0 4A
Tx:01 02 00 00 00 03 38 0B
功能码为03 的modbus RTU报文
Rx:01 03 00 00 00 02 C4 0B
Tx:01 03 04 00 0B 00 16 0A 3F
功能码为04 的modbus RTU报文
Rx:01 04 00 00 00 02 71 CB
Tx:01 04 04 00 06 00 62 9A 6C
注:ModBus中RTU报文和TCP报文主要区别就是TCP报文中会有一个MBAP头,然后没有最后的CRC校验码,其余各项表示的含义基本一致
功能码为01 的modbus TCP报文
Tx:00 14 00 00 00 06 01 01 00 00 00 03
Rx:00 14 00 00 00 04 01 01 01 06
此处06代表00000110,表示2,3位线圈为开启状态
功能码为02 的modbus TCP报文
Tx:00 00 00 00 00 06 01 02 00 00 00 03
Rx:00 00 00 00 00 04 01 02 01 01
7.功能码为03 的modbus TCP报文
Tx:00 0A 00 00 00 06 01 03 00 00 00 03
Rx:00 0A 00 00 00 09 01 03 06 00 00 00 00 00 00
功能码为04 的modbus TCP报文
Tx:00 08 00 00 00 06 01 04 00 00 00 02
Rx:00 08 00 00 00 07 01 04 04 00 06 00 62
9.功能码为05 的modbus TCP报文
Tx:00 6C 00 00 00 06 01 05 00 00 FF 00
Rx:00 6C 00 00 00 06 01 05 00 00 FF 00
注:(1)FF 00 表示从关状态到开状态
00 00 表示从开状态到关状态
(2)从机在收到主机报文后执行 相应的操作后原文返回
(3)05功能码主站只能修改从站的一个线圈,即一位的数据,不允许发多位
功能码为06 的modbus TCP报文
Tx:02 D4 00 00 00 06 01 06 00 00 00 E8
Rx:02 D4 00 00 00 06 01 06 00 00 00 E8
注:00 00为 写入地址,00 E8为写入的数据
功能码为15 的modbus TCP报文
Tx:02 DD 00 00 00 08 01 0F 00 00 00 05 01 0B
Rx:02 DD 00 00 00 06 01 0F 00 00 00 05
注:0B 为0000 1011
当超过修改线圈数超过8位时,从左到右从低位到高位按字节排列,在单个字节 中按 从 高位到低位的顺序排列。
功能码为16 的modbus TCP报文
Tx:05 75 00 00 00 11 01 10 00 00 00 05 0A 00 06 00 07 00 08 00 01 00 09
Rx:05 75 00 00 00 06 01 10 00 00 00 05
注:传送数据的顺序就是从低位到高位以此发送,每个数据占两个字节