Modbus协议详解

博主介绍

::: hljs-center

?作者介绍:中国DBA联盟(ACDU)成员。目前从事工业自动化软件开发工作。擅长C#、Java、机器视觉、底层算法等语言。2019年成立柒月软件工作室,2021年注册苏州凯捷智能科技有限公司
?如果文章对你有帮助,欢迎关注、点赞、收藏(一键三连)
?️
? 有任何问题欢迎私信,看到会及时回复
微信公众号:苏州程序大白

:::

Modbus概述

Modbus通信协议由Modicon公司(现已经为施耐德公司并购,成为其旗下的子品牌)于1979年发明的,是全球最早用于工业现场的总线规约。由于其免费公开发行,使用该协议的厂家无需缴纳任何费用,Modbus通信协议采用的是主从通信模式(即Master/Slave通信模式),其在分散控制方面应用极其广泛,从而使得Modbus协议在全球得到了广泛的应用。

Modbus通信协议具有多个变种,其具有支持串口(主要是RS-485、RS-232总线),以太网多个版本,其中最著名的是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协议用于表示信息帧的功能,常用的功能码有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系统改变离散量输入和输入寄存器的数值,而上位机程序不能改变的数据类型,在数据读写上表现为只读,而内部比特或者物理线圈和内部寄存器或物理输出寄存器(保持寄存器)则是上位机应用程序可以改变的数据类型,在数据读写上表现为可读可写。
在这里插入图片描述

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字节

读取的寄存器数据