ModBus协议报文格式解析说明

什么是Modbus?

       Modbus协议是一个master/slave架构的协议。有一个节点是master节点,其他使用Modbus协议参与通信的节点是slave节点。每一个slave设备都有一个唯一的地址。在串行和MB+网络中,只有被指定为主节点的节点可以启动一个命令(在以太网上,任何一个设备都能发送一个Modbus命令,但是通常也只有一个主节点设备启动指令)。

       一个ModBus命令包含了打算执行的设备的Modbus地址。所有设备都会收到命令,但只有指定位置的设备会执行及回应指令(地址0例外,指定地址0的指令是广播指令,所有收到指令的设备都会运行,不过不回应指令)。所有的Modbus命令包含了检查码,以确定到达的命令没有被破坏。基本的ModBus命令能指令一个RTU改变它的寄存器的某个值,控制或者读取一个I/O端口,以及指挥设备回送一个或者多个其寄存器中的数据。

      以上都是参考百度百科的解释说明,还是没有看明白的同学可以先不用管,至少现在我们需要有一个概念,modbus通信中会有两个设备,一个是主机poll端和从机salve端,接下来看下面的进一步说明。

Modbus TCP/IP协议格式

  • 主机poll端发送读写报文样例如下,该报文对应的功能码选择的04。

07 9B 00 00 00 06 01 04 00 00 00 0A

数据

含义

07 9B

主机发出的检验信息,从机slave将这个两个字节放在响应报文中

00 00

表示协议标识符,00 00为modbus的TCP/IP协议

00 06

数据长度,用来指示接下来数据的长度,单位字

01

设备地址,用以标识连接在串行线或者网络上的远程服务端的地址。

04

功能码,此时代码04为读取InputRegisters寄存器数据

00 00

读取寄存器起始地址

00 0A

读取寄存器长度,16进制

以上报文中前6个字节称作为modbus的头字节,后面为查询命令数据段PDU。主机需要查询从机寄存器从0开始后面10个寄存器的值,根据该命令从机返回的报文如下。

  • 从机slave端返回对应04功能码查询的数据报文样例

07 9B 00 00 00 17 01 04 14 41 D0 FB E7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

数据

含义

07 9B

此次通信事务处理标识符,应答报文要求与先前对应的请求保持一致

00 00

协议标识符,与先前对应的请求保持一致

00 17

数据长度,用来指示接下来数据的长度,单位字节

01

设备地址,应答报文要求与先前对应的请求保持一致

04

功能码,正常情况下应答报文要求与先前对应的请求保持一致,如果出错则返回0x80+先前的功能码(读取错误码83)

14

接下来的数据的字节长度,注意是十六进制的

41 D0 FB E7....

被读取的保持寄存器中的数据值

这里从机返回十个寄存器的值,每两个字节为一个int整型(如果是float或double类型则是四个字节),即 41 D0是int整型数据,查看的话需要转化为int整型,这里就不在赘述了,这里提供一个Java的方法转换,可以直接调用。


 
 
   
   
   
   
  1. // String类型为 41D0 的16进制类型的字符串
  2. // 41D0 转化为10进制为16848
  3. public int CovertTo(String str){
  4. return Integer.parseInt(str, 16);
  5. }
  • 主机poll端发送位寄存器查询报文格式如下,对应查询功能码为01。

04 E2 00 00 00 06 01 01 00 00 00 0A 

数据

含义

04 E2

此次通信事务处理标识符,一般每次通信之后将被要求加1以区别不同的通信数据报文

00 00

表示协议标识符,00 00为modbus的TCP/IP协议

00 06

数据长度,用来指示接下来数据的长度,单位字

01

设备地址,用以标识连接在串行线或者网络上的远程服务端的地址

01

功能码,此时代码01为读取Coils寄存器数据

00 00

起始地址

00 0A

寄存器数量,十六进制

这段报文读取从机位寄存器Coils的0到9地址的值,但是从机返回还是16进制数据,不能按照二进制进行传输,需要将从机的位进制寄存器排列起来并按一定规则进行组合成16进制数,规定两个字节算一个最小单位,即 00 是modbus报文最小传输单位,两个字节等于8位,数据不够的话自动补零,所以主机查询从机0到9的寄存器地址值,最后返回的是0到15的寄存器的值,长度必须是8的倍数,比如查长度为10返回长度16,查17返回的是长度24。这里可以参考一个例子说明,从机的前8位设置值如下。

0 1 2 3 4 5 6 7
0 0 1 1 0 1 0 1

slave模拟器设置如下:

  • 从机slave端返回对应01功能码查询的数据报文样例

04 E2 00 00 00 05 01 01 02 AC 00

数据

含义

04 E2

此次通信事务处理标识符,应答报文要求与先前对应的请求保持一致

00 00

协议标识符,与先前对应的请求保持一致

00 05

数据长度,用来指示接下来数据的长度,单位字节

01

设备地址,应答报文要求与先前对应的请求保持一致

01

功能码,正常情况下应答报文要求与先前对应的请求保持一致,如果出错则返回0x80+先前的功能码(读取错误码83)

02

接下来的数据的字节长度,注意是十六进制的

AC 00

被读取的保持寄存器中的数据值

从机返回的报文数据只有两个字节,但是它包含了16位Coils寄存器的值,AC 02 需要转化为二进制。

从机的寄存器位值按顺序应该是 00110101 00000000,编码机制是每8位算作一个单位,并且高位与低位相反,通俗点将就是每8位将数据翻转过来,所以转化为编码为 10101100 0000000, 再转化为16进制则为 AC 00。

  • Modbus写报文请求和响应报文格式

主机的写报文请求格式则与从机的数据查询响应报文格式类似,都是头字节加上数据段,这里就不要举例了。

从机的写报文响应则与主机读报文的请求格式类似。

 

转载至:https://blog.csdn.net/lsh159357/article/details/84938546

你可能感兴趣的:(Modbus)