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报文头事务处理标识符Hi10x15
-事务处理标识符Lo10x01
-协议标识符20x0000
-长度20x0006
-单元标识符10xFF
MODBUS请求功能码10x03
-起始地址20x0005
-寄存器数量20x0001

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值