ModbusTCP协议分析

ModbusTCP与ModbusUDP的报文格式是一样的,它们之间的区别其实就是TCP与UDP的区别,因此下面就针对ModbusTCP的协议进行分析,ModbusTCP与ModbusRtu(ModbusASCII)之间的区别如下图:




java实现modbus从机 modbustcp java_网络


从上图可以看出,ModbusTCP在Modbus串行通信的基础上,去除了校验(由于TCP本身就带有校验和)和设备地址(ModbusTCP弱化了设备地址,用IP地址来取代),再加上MBAP报文头(占7 bytes),下面针对MBAP进行分析说明:


长度

说明

客户机

服务器

事务处理标识符

2字节

Modbus请求/响应事务处理的标识

客户机启动

复制响应

协议标识符

2字节

0=Modbus协议

客户机启动

复制响应

长度

2字节

长度之后的字节总数

客户机启动

服务器启动

单元标识符

1字节

串行链路或其它总线的从站识别

客户端启动

复制响应


下面针对具体报文进行分析,Modbus协议在以太网链路上的报文格式如下所示:


事务处理标识符

协议标识符

长度

单元标识符

功能码

数据

2 bytes

2 bytes

2 bytes

1 byte

1 byte

N bytes


有了以上理论基础之后,下面针对各个功能码进行详细分析:

读取输出线圈

发送报文格式如下:


java实现modbus从机 modbustcp java_运维_02


发送报文含义:读取服务器1号从站输出线圈,起始地址为0x13=19,对应地址为00020,线圈数量为0x1B=27,即读取1号从站输出线圈,地址从00020-00046,共27个线圈的状态值。

这里值得注意一下,协议中的起始地址指的是索引,后面的地址指的是具体地址,对于任意一个存储区,索引都是从0开始的,但是对应的具体地址,与存储区是相关的,比如输出线圈,0对应00001;输入线圈,0对应10001;输入寄存器,0对应30001;保持寄存器,0对应40001。

返回报文格式如下:


java实现modbus从机 modbustcp java_运维_03


返回报文含义:返回服务器1号从站输出线圈00020-00046,共27个线圈的状态值,返回字节数为4个,分别为CD 6B B2 05。

CD=1100 1101 对应 00020-00027

6B=0110 1011 对应 00028-00035

B2=1011 0010 对应 00036-00043

05=0000 0101 对应 00044-00046

读取输入线圈

发送报文格式如下:


java实现modbus从机 modbustcp java_服务器_04


发送报文含义:读取服务器1号从站输入线圈,起始地址为0xC4=196,对应地址为10197,线圈数量为0x1D=29,即读取1号从站输入线圈,地址从10197-10225,共29个线圈的状态值。

返回报文格式如下:


java实现modbus从机 modbustcp java_Powered by 金山文档_05


返回报文含义:返回服务器1号从站输入线圈10197-10225,共29个线圈的状态值,返回字节数为4个,分别为CD 6B B2 05。

CD=1100 1101 对应 10197-10204

6B=0110 1011 对应 10205-10212

B2=1011 0010 对应 10213-10220

05=0000 0101 对应 10221-10225

读取保持寄存器

发送报文格式如下:


java实现modbus从机 modbustcp java_网络_06


发送报文含义:读取服务器1号从站保持寄存器,起始地址为0x6B=107,对应地址为40108,寄存器数量为0x02=2,即读取1号从站保持寄存器,地址从40108-40109,共2个寄存器的数值。

返回报文格式如下:


java实现modbus从机 modbustcp java_服务器_07


返回报文含义:返回服务器1号从站保持寄存器40108-40109,共2个寄存器的数值,返回字节数为4个,分别为02 2B 01 06,40108对应数值为0x022B,40109对应数值为0x0106。

读取输入寄存器

发送报文格式如下:


java实现modbus从机 modbustcp java_运维_08


发送报文含义:读取服务器1号从站输入寄存器,起始地址为0x6B=107,对应地址为30108,寄存器数量为0x02=2,即读取1号从站保持寄存器,地址从30108-30109,共2个寄存器的数值。

返回报文格式如下:


java实现modbus从机 modbustcp java_服务器_09


返回报文含义:返回服务器1号从站输入寄存器30108-30109,共2个寄存器的数值,返回字节数为4个,分别为02 2B 01 06,30108对应数值为0x022B,30109对应数值为0x0106。

预置单线圈

发送报文格式如下:


java实现modbus从机 modbustcp java_java实现modbus从机_10


发送报文含义:预置服务器1号从站单个线圈的值,线圈地址为0x00AC=172,对应地址为00173,断通标志0xFF00表示置位,0x000表示复位,即置位1号从站输出线圈00173。

返回报文格式如下:


java实现modbus从机 modbustcp java_运维_11


返回报文含义:预置单输出线圈原报文返回。

预置单寄存器

发送报文格式如下:


java实现modbus从机 modbustcp java_网络_12


发送报文含义:预置服务器1号从站单个保持寄存器的值,寄存器地址为0x0087=135,对应地址为40136,写入值为0x039E,即预置1号从站保持寄存器40136值为0x039E。

返回报文格式如下:


java实现modbus从机 modbustcp java_运维_13


返回报文含义:预置单保持寄存器原报文返回。

预置多线圈

发送报文格式如下:


java实现modbus从机 modbustcp java_java实现modbus从机_14


发送报文含义:预置服务器1号从站多个线圈的值,线圈地址为0x0013=19,对应地址为00020,线圈数为0x0A=10,写入值为0xCD00,即预置1号从站线圈00020-00027=0xCD=1100 1101,00028-00029=0x00=0000 0000。

返回报文格式如下:


java实现modbus从机 modbustcp java_java实现modbus从机_15


返回报文含义:预置多输出线圈返回报文是在原报文基础上除去字节数及具体字节后返回。

预置多寄存器

发送报文格式如下:


java实现modbus从机 modbustcp java_运维_16


发送报文含义:预置服务器1号从站多个寄存器的值,寄存器地址为0x0087=135,起始地址为40136,寄存器数量为0x02=2,结束地址为40137,写入值为0xCD00和0x0A10,即预置1号从站寄存器40136=0x0105,40137=0x0A10。

返回报文格式如下:


java实现modbus从机 modbustcp java_运维_17


返回报文含义:预置多保持寄存器返回报文是在原报文基础上除去字节数及具体字节后返回。

异常错误码说明



数据类型

功能描述

功能码

功能码(十六进制)

异常功能码

比特访问

物理离散量输入

读输入离散量

02

0x02

0x82

内部比特或者物理线圈

读线圈

01

0x01

0x81

写单个线圈

05

0x05

0x85

写多个线圈

15

0x0F

0x8F


16比特访问

输入存储器

读输入寄存器

04

0x04

0x84

内部存储器或物理输出存储器(保持寄存器)

读多个寄存器

03

0x03

0x83

写单个寄存器

06

0x06

0x86

写多个寄存器

16

0x10

0x90

读/写多个寄存器

23

0x17

0x97

屏蔽写寄存器

22

0x16

0x96


文件记录访问

读文件记录

20

0x14


写文件记录

21

0x15



其中物理离散量输入和输入寄存器只能有I/O系统提供的数据类型,即只能是由I/O系统改变离散量输入和输入寄存器的数值,而上位机程序不能改变的数据类型,在数据读写上表现为只读,而内部比特或者物理线圈和内部寄存器或物理输出寄存器(保持寄存器)则是上位机应用程序可以改变的数据类型,在数据读写上表现为可读可写。

错误代码表


代码

名称

含义

01

非法功能

对于服务器(或从站)来说,询问中接收到的功能码是不可允许的操作,可能是因为功能码仅适用于新设备而被选单元中不可实现同时,还指出服务器(或从站)在错误状态中处理这种请求,例如:它是未配置的,且要求返回寄存器值。

02

非法数据地址

对于服务器(或从站)来说,询问中接收的数据地址是不可允许的地址,特别是参考号和传输长度的组合是无效的。对于带有100个寄存器的控制器来说,偏移量96和长度4的请求会成功,而偏移量96和长度5的请求将产生异常码02。

03

非法数据值

对于服务器(或从站)来说,询问中包括的值是不可允许的值。该值指示了组合请求剩余结构中的故障。例如:隐含长度是不正确的。modbus协议不知道任何特殊寄存器的任何特殊值的重要意义,寄存器中被提交存储的数据项有一个应用程序期望之外的值。

04

从站设备故障

当服务器(或从站)正在设法执行请求的操作时,产生不可重新获得的差错。

05

确认

与编程命令一起使用,服务器(或从站)已经接受请求,并且正在处理这个请求,但是需要长持续时间进行这些操作,返回这个响应防止在客户机(或主站)中发生超时错误,客户机(或主机)可以继续发送轮询程序完成报文来确认是否完成处理。

07

从属设备忙

与编程命令一起使用,服务器(或从站)正在处理长持续时间的程序命令,当服务器(或从站)空闲时,客户机(或主站)应该稍后重新传输报文。

08

存储奇偶性差错

与功能码20和21以及参考类型6一起使用,指示扩展文件区不能通过一致性校验。服务器(或从站)设备读取记录文件,但在存储器中发现一个奇偶校验错误。客户机(或主机)可重新发送请求,但可以在服务器(或从站)设备上要求服务。

0A

不可用网关路径

与网关一起使用,指示网关不能为处理请求分配输入端口值输出端口的内部通信路径,通常意味着网关是错误配置的或过载的。

0B

网关目标设备响应失败

与网关一起使用,指示没有从目标设备中获得响应,通常意味着设备未在网络中。