Modbus TCP协议概述

1 简介

modbus由MODICON公司于1979年开发,是一种工业现场总线协议标准。Modbus协议是一项应用层报文传输协议,包括ASCII、RTU、TCP三种报文类型。标准的Modbus协议物理层接口有RS232、RS422、RS485和以太网接口,采用master/slave方式通信。

1996年施耐德公司推出基于以太网TCP/IP的modbus协议:modbusTCP
简单的理解一下Modbus TCP/IP协议的内容,就是去掉了modbus协议本身的CRC校验,增加了MBAP 报文头。TCP/IP上的MODBUS的请求/响应如下图所示:

2 ModbusTCP数据帧

ModbusTCP的数据帧可分为两部分:报文头(MBAP)+帧结构(PDU)

2.1 报文头MBAP

MBAP为报文头,长度为7字节,组成如下:

长度 描述 客户机 服务器
事务元标识符 2个字节 MODBUS请求/响应事务处理的识别码 客户机启动 服务器从接收的
协议标识符 2个字节 0=MODBUS协议 客户机启动 服务器从接收的请求中重新复制
长度 2个字节 以下字节的数量 客户机启动(请求) 服务器(响应)启动
单元标识符 1个字节 串行链路或其它总线上连接的远程从站的识别码 客户机启动 服务器从接收的请求中重新复制

事务处理标识 : 可以理解为报文的序列号,一般每次通信之后就要加1以区别不同的通信数据报文。
协议标识符 : modbus协议标识符为0x00,0x00;
长度 : 表示接下来的数据长度,单位为字节。
单元标识符 : 可以理解为设备地址。

分配串行链路上MODBUS从站设备地址为1~247(10进制),地址0作为广播地址。
对 TCP/IP 来说,利用IP地址寻址MODBUS服务器;因此,MODBUS单元标识符是无用的。必需使用值0xFF。

2.2 MODBUS请求的生成

在收到来自用户应用的需求后,客户端必须生成一个MODBUS请求,并发送到TCP管理。下表显示MODBUS请求ADU编码:

类型 描述 字节大小 实例
MBAP报文头 事务处理标识符Hi 1 0x15
- 事务处理标识符Lo 1 0x01
- 协议标识符 2 0x0000
- 长度 2 0x0006
- 单元标识符 1 0xFF
MODBUS请求 功能码 1 0x03
- 起始地址 2 0x0005
- 寄存器数量 2 0x0001

2.3 MODBUS响应的生成

一旦处理请求,MODBUS 服务器必须使用适当的MODBUS服务器事务处理生成一个响应,并且必须将响应发送到TCP管理组件。

根据处理结果,可以生成两类响应:

  • 肯定的MODBUS响应:
    • 响应功能码 = 请求功能码
  • MODBUS异常响应:
    • 目的是为客户机提供与处理过程检测到的错误相关的信息
    • 响应功能码 = 请求功能码+0x80
    • 提供异常码来表明出错的原因。
异常码 MODBUS名称 备注
01 非法的功能码 服务器不了解功能码
02 非法的数据地址 与请求有关
03 非法的数据值 与请求有关
04 服务器故障 在执行过程中,服务器故障
05 确认 服务器接受服务调用,但是需要相对长的时间完成服务。因此,服务器仅返回一个服务调用接收的确认。
06 服务器繁忙 服务器不能接受MODBUS请求PDU。客户应用由责任决定是否和何时重发请求。
0A 网关故障 网关路经是无效的。
0B 网关故障 目标设备没有响应。网关生成这个异常信息。

2.4 帧结构PDU

PDU由功能码+数据组成。功能码为1字节,数据长度不定,由具体功能决定。

2.4.1 功能码

modbus的操作对象有四种:线圈、离散输入、输入寄存器、保持寄存器。

对象 含义
线圈 PLC的输出位,开关量,在MODBUS中可读可写
离散量 PLC的输入位,开关量,在MODBUS中只读
输入寄存器 PLC中只能从模拟量输入端改变的寄存器,在MODBUS中只读
保持寄存器 PLC中用于输出模拟量信号的寄存器,在MODBUS中可读可写

根据对象的不同,modbus的功能码有:

代码 中文名称 英文名 位操作/字操作 操作数量
0x01 读线圈状态 READ COIL STATUS 位操作 单个或多个
0x02 读离散输入状态 READ INPUT STATUS 位操作 单个或多个
0x03 读保持寄存器 READ HOLDING REGISTER 字操作 单个或多个
0x04 读输入寄存器 READ INPUT REGISTER 字操作 单个或多个
0x05 写线圈状态 WRITE SINGLE COIL 位操作 单个
0x06 写单个保持寄存器 WRITE SINGLE REGISTER 字操作 单个
0x0F 写多个线圈 WRITE MULTIPLE COIL 位操作 多个
0x10 写多个保持寄存器 WRITE MULTIPLE REGISTER 字操作 多个
2.2.2 PDU详细结构

0x01:读线圈
在从站中读1~2000个连续线圈状态,ON=1,OFF=0

  • 请求:MBAP 功能码 起始地址H 起始地址L 数量H 数量L(共12字节)
  • 响应:MBAP 功能码 数据长度 数据(一个地址的数据为1位)
  • 如:在从站0x01中,读取开始地址为0x0002的线圈数据,读0x0008位
    00 01 00 00 00 06 01 01 00 02 00 08
  • 回:数据长度为0x01个字节,数据为0x01,第一个线圈为ON,其余为OFF
    00 01 00 00 00 04 01 01 01 01

0x05:写单个线圈

将从站中的一个输出写成ON或OFF,0xFF00请求输出为ON,0x000请求输出为OFF

  • 请求:MBAP 功能码 输出地址H 输出地址L 输出值H 输出值L(共12字节)
  • 响应:MBAP 功能码 输出地址H 输出地址L 输出值H 输出值L(共12字节
  • 如:将地址为0x0003的线圈设为ON
    00 01 00 00 00 06 01 05 00 03 FF 00
  • 回:写入成功
    00 01 00 00 00 06 01 05 00 03 FF 00

0x0F:写多个线圈
将一个从站中的一个线圈序列的每个线圈都强制为ON或OFF,数据域中置1的位请求相应输出位ON,置0的位请求响应输出为OFF

  • 请求:MBAP 功能码 起始地址H 起始地址L 输出数量H 输出数量L 字节长度 输出值H 输出值L
  • 响应:MBAP 功能码 起始地址H 起始地址L 输出数量H 输出数量L

0x02:读离散量输入

从一个从站中读1~2000个连续的离散量输入状态

  • 请求:MBAP 功能码 起始地址H 起始地址L 数量H 数量L(共12字节)
  • 响应:MBAP 功能码 数据长度 数据(长度:9+ceil(数量/8))
  • 如:从地址0x0000开始读0x0012个离散量输入
    00 01 00 00 00 06 01 02 00 00 00 12
  • 回:数据长度为0x03个字节,数据为0x01 04 00,表示第一个离散量输入和第11个离散量输入为ON,其余为OFF
    00 01 00 00 00 06 01 02 03 01 04 00

0x04:读输入寄存器

从一个远程设备中读1~2000个连续输入寄存器

  • 请求:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L(共12字节)
  • 响应:MBAP 功能码 数据长度 寄存器数据(长度:9+寄存器数量×2)
  • 如:读起始地址为0x0002,数量为0x0005的寄存器数据
    00 01 00 00 00 06 01 04 00 02 00 05
  • 回:数据长度为0x0A,第一个寄存器的数据为0x0c,其余为0x00
    00 01 00 00 00 0D 01 04 0A 00 0C 00 00 00 00 00 00 00 00

0x03:读保持寄存器

从远程设备中读保持寄存器连续块的内容

  • 请求:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L(共12字节)
  • 响应:MBAP 功能码 数据长度 寄存器数据(长度:9+寄存器数量×2)
  • 如:起始地址是0x0000,寄存器数量是 0x0003
    00 01 00 00 00 06 01 03 00 00 00 03
  • 回:数据长度为0x06,第一个寄存器的数据为0x21,其余为0x00
    00 01 00 00 00 09 01 03 06 00 21 00 00 00 00

0x06:写单个保持寄存器

在一个远程设备中写一个保持寄存器

  • 请求:MBAP 功能码 寄存器地址H 寄存器地址L 寄存器值H 寄存器值L(共12字节)
  • 响应:MBAP 功能码 寄存器地址H 寄存器地址L 寄存器值H 寄存器值L(共12字节)
  • 如:向地址是0x0000的寄存器写入数据0x000A
    00 01 00 00 00 06 01 06 00 00 00 0A
  • 回:写入成功
    00 01 00 00 00 06 01 06 00 00 00 0A

0x10:写多个保持寄存器

在一个远程设备中写连续寄存器块(1~123个寄存器)

  • 请求:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L 字节长度 寄存器值(13+寄存器数量×2)
  • 响应:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L(共12字节)
  • 如:向起始地址为0x0000,数量为0x0001的寄存器写入数据,数据长度为0x02,数据为0x000F
    00 01 00 00 00 09 01 10 00 00 00 01 02 00 0F
  • 回:写入成功
    00 01 00 00 00 06 01 10 00 00 00 01

3 ModbusTCP通信

3.1 通信方式

modbus设备可分为主站(poll)和从站(slave)。主站只有一个,从站有多个,主站向各从站发送请求帧,从站给予响应。在使用TCP通信时,主站为client端,主动建立连接;从站为server端,等待连接。

  • 主站请求:功能码+数据
  • 从站正常响应:请求功能码+响应数据
  • 从站异常响应:异常功能码+异常码,其中异常功能码即将请求功能码的最高有效位置1,异常码指示差错类型
  • 注意:需要超时管理机制,避免无期限的等待可能不出现的应答

IANA(Internet Assigned Numbers Authority,互联网编号分配管理机构)给Modbus协议赋予TCP端口号为502,这是目前在仪表与自动化行业中唯一分配到的端口号。

通信过程

  1. connect 建立TCP连接
  2. 准备Modbus报文
  3. 使用send命令发送报文
  4. 在同一连接下等待应答
  5. 使用recv命令读取报文,完成一次数据交换
  6. 通信任务结束时,关闭TCP连接

4 基于Qt实现

Qt中提供了QModbusTcpClientQModbusTcpServer两个类分别来实现客户端和服务器端,具体参见官网例子:
Modbus Master example
Modbus Slave example

你可能感兴趣的:(modbus)