1、协议概述
<br />modbus是OSI模型第7层上的应用层报文传输协议,它在连接至不同类型总线或网络的设备之间提供客户机/服务器通信。
modbus是一个请求/应答协议,并且提供功能码规定的服务。modbus功能码是modbus请求/应答PDU的元素。本文档的作用是帮助大家解析modbus报文。
2、数据模型
Modbus以一系列具有不同特征表格上的数据模型为基础。四个基本表格为:
基本表格 | 对象类型 | 访问类型 | 内容 |
---|---|---|---|
线圈 | 1比特 | 读/写 | 通过应用程序改变这种类型数据 |
离散量输入 | 1比特 | 只读 | I/O系统提供这种数据类型 |
保持寄存器 | 16比特 | 读/写 | 通过应用程序改变这种类型数据 |
输入寄存器 | 16比特 | 只读 | I/O系统提供这种数据类型 |
3、报文格式
目前,我们使用的modbus协议主要有两种,通过以太网的TCP/IP通信的modbus_tcp协议及串口通信的modbus_rtu。
modbus协议定义了一个与基础通信层无关的简单协议数据单元(PDU)。特定总线或网络上的modbus协议映射能够在应用数据单元(ADU)上引入一些附加域。
modbus_tcp和modbus_rtu协议的PDU是一致的,modbus_tcp会在PDU之前加一个七字节的MBAP报文头,并且没有差错校验;modbus_rtu会在PDU前加一个字节的地址域,后面跟两个字节的校验。
Modbus_tcp报文:
Modbus_rtu报文:
注意:
Modbus协议使用big-endian表示地址和数据项。这意味着当发射多个字节的数据时,首先发送最高有效位。
Modbus报文的地址从0开始,设备中的地址往往从1开始。
4、PDU解析、功能码
目前系统中主要实现六种功能码。
4.1、功能码:01(读线圈)
在一个远程设备中,使用该功能码读取线圈的1至2000连续状态。请求PDU详细说明了起始地址,即指定的第一个线圈地址和线圈编号。从零开始寻址线圈。因此寻址线圈1-16为0-15。
根据数据域的每个比特将响应报文中的线圈分成为一个线圈。指示状态为1=ON和0=OFF。第一个数据字节的 LSB(最低有效位)包括在询问中寻址的输出。其它线圈依次类推,一直到这个字节的高位端为止,并在后续字节中从低位到高位的顺序。
如果返回的输出数量不是八的倍数,将用零填充最后数据字节中的剩余比特(一直到字节的高位端)。字节数量域说明了数据的完整字节数。
请求PDU:01 00 13 00 13
01 00 13 00 13
功能码 起始地址 线圈数量
报文:读取线圈20-38的数据。
响应PDU:01 03 CD 6B 05
01 03 CD 6B 05
功能码 报文长度 输出状态27-20 输出状态35-28 输出状态38-36
报文:输出27-20的状态表示为十六进制字节值CD,或二进制1100 1101。输出27是这个字节的MSB,输出20是LSB。
通常,将一个字节内的比特表示为MSB位于左侧,LSB位于右侧。第一字节的输出从左至右为27至20。下一个字节的输出从左到右为35至28。当串行发射比特时,从LSB向MSB传输:20……27、28……35等等。
在最后的数据字节中,将输出状态38-36表示为十六进制字节值05,或二进制0000 0101。输出38是左侧第六个比特位置,输出36是这个字节的LSB。用零填充五个剩余高位比特。
4.2、功能码:02(读离散量输入)
在一个远程设备中,使用该功能码读取离散量输入的1至2000连续状态。请求PDU详细说明了起始地址,即指定的第一个输入地址和输入编号。从零开始寻址输入。因此寻址输入1-16为0-15。
根据数据域的每个比特将响应报文中的离散量输入分成为一个输入。指示状态为1=ON和0=OFF。第一个数据字节的LSB(最低有效位)包括在询问中寻址的输入。其它输入依次类推,一直到这个字节的高位端为止,并在后续字节中从低位到高位的顺序。
如果返回的输入数量不是八的倍数,将用零填充最后数据字节中的剩余比特(一直到字节的高位端)。字节数量域说明了数据的完整字节数。
请求PDU:02 00 C4 00 16
02 00 C4 00 16
功能码 起始地址 输入数量
报文:请求读取离散量输入197-218的数据。
响应PDU:02 03 AC DB 35
02 03 AC DB 35
功能码 报文长度 输入状态204-197 输入状态212-205 输入状态218-213
报文:将离散量输入状态204-197表示为十六进制字节值AC,或二进制1010 1100。输入204是这个字节的MSB,输入197是这个字节的LSB。
将离散量输入状态218-213表示为十六进制字节值35,或二进制0011 0101。输入218位于左侧第3比特,输入213是LSB。
4.3、功能码:03(读保持寄存器)
在一个远程设备中,使用该功能码读取保持寄存器连续块的内容。请求PDU说明了起始寄存器地址和寄存器数量。从零开始寻址寄存器。因此,寻址寄存器1-16为0-15。
将响应报文中的寄存器数据分成每个寄存器有两字节,在每个字节中直接地调整二进制内容。
对于每个寄存器,第一个字节包括高位比特,并且第二个字节包括低位比特。
请求PDU:03 00 6B 00 03
03 00 6B 00 03
功能码 起始地址 寄存器数量
报文:请求寄存器108-110的数据。
响应PDU:03 06 02 2B 00 00 00 64
03 06 02 2B 00 00 00 64
功能码 报文长度 寄存器108值 寄存器109值 寄存器110值
报文:将寄存器108的内容表示为两个十六进制字节值02 2B,或十进制555。将寄存器109-110的内容分别表示为十六进制00 00和00 64,或十进制0和100。
4.4、功能码:04(读输入寄存器)
在一个远程设备中,使用该功能码读取1至大约125的连续输入寄存器。请求PDU说明了起始地址和寄存器数量。从零开始寻址寄存器。因此,寻址输入寄存器1-16为0-15。
将响应报文中的寄存器数据分成每个寄存器为两字节,在每个字节中直接地调整二进制内容。
对于每个寄存器,第一个字节包括高位比特,并且第二个字节包括低位比特。
请求PDU:04 00 08 00 01
04 00 08 00 01
功能码 起始地址 读输入寄存器数量
报文:请求读输入寄存器09值。
响应PDU:04 02 00 0A
04 02 00 0A
功能码 报文长度 输入寄存器09值
报文:将输入寄存器9的内容表示为两个十六进制字节值00 0A,或十进制10。
4.5、功能码:05(写单个线圈)
在一个远程设备上,使用该功能码写单个输出为ON或OFF。
请求数据域中的常量说明请求的ON/OFF状态。十六进制值FF 00请求输出为ON。十六进制值00 00请求输出为OFF。其它所有值均是非法的,并且对输出不起作用。
请求PDU说明了强制的线圈地址。从零开始寻址线圈。因此,寻址线圈1为0。线圈值域的常量说明请求的ON/OFF状态。十六进制值0xFF00请求线圈为ON。十六进制值0x0000请求线圈为OFF。其它所有值均为非法的,并且对线圈不起作用。
正常响应是请求的应答,在写入线圈状态之后返回这个正常响应。
请求PDU:05 00 AC FF 00
05 00 AC FF 00
功能码 输出地址 输出值
报文:请求线圈173为ON。
响应PDU:05 00 AC FF 00
05 00 AC FF 00
功能码 输出地址 输出值
报文:应答写线圈173为ON。
4.6、功能码:06(写单个寄存器)
在一个远程设备中,使用该功能码写单个保持寄存器。
请求PDU说明了被写入寄存器的地址。从零开始寻址寄存器。因此,寻址寄存器1为0。
正常响应是请求的应答,在写入寄存器内容之后返回这个正常响应。
请求PDU:06 00 01 00 03
06 00 01 00 03
功能码 寄存器地址 寄存器值
报文:请求将十六进制00 03写入寄存器2.
响应PDU:06 00 01 00 03
06 00 01 00 03
功能码 寄存器地址 寄存器值
报文:响应请求将十六进制00 03写入寄存器2.
5、Modbus_tcp ADU解析
这节描述了MODBUS TCP/IP网络中进行的MODBUS请求或响应的封装。在TCP/IP上使用一种专用报文头识别MODBUS应用数据单元。将这种报文头称为MBAP报文头(MODBUS 协议报文头)。
MBAP报文头包括下列域:
域 | 长度 | 描述 | 客户机 | 服务器 |
---|---|---|---|---|
事务标识符 | 2个字节 | MODBUS 请求/响应事务处理的识别码 | 客户机启动 | 服务器从接收的请求中重新复制 |
协议标识符 | 2个字节 | 0=MODBUS协议 | 客户机启动 | 服务器从接收的请求中重新复制 |
长度 | 2个字节 | 之后报文字节数 | 客户机启动(请求) | 服务器(响应)启动 |
单元标识符 | 1个字节 | 串行链路或其他总线上连接的远程从站的识别码/站址 | 客户机启动 | 服务器从接收的请求中重新复制 |
报文头为7个字节长:
事务处理标识符:用于事务处理配对。在响应中,MODBUS服务器复制请求的事务处理标识符。
协议标识符:用于系统内的多路复用。通过值0识别MODBUS协议。
长度:长度域是下一个域的字节数,包括单元标识符和数据域。
单元标识符:为了系统内路由,使用这个域。专门用于通过以太网TCP-IP 网络和MODBUS串行链路之间的网关对MODBUS或MODBUS+串行链路从站的通信。 MODBUS客户机在请求中设置这个域,在响应中服务器必须利用相同的值返回这个域。
在注册的502端口上利用TCP发送所有MODBUS/TCP ADU。
注:用Big-endian 编码不同域。
请求ADU:01 03 00 00 00 06 01 01 0A CB 00 10
01 03 00 00 00 06 0101 0A CB 00 10
事务标识符 协议标识符 后续报文长度 站址MODBUS PDU
报文:报文事务标识0x0103,modbus协议,后续报文长度6个字节,站址1,PDU解析见上节。
响应ADU:01 03 00 00 00 05 01 01 02 0A 1B
01 03 00 00 00 05 0101 020A1B
事务标识符 协议标识符 后续报文长度 站址MODBUS PDU
报文:报文事务标识0x0103,modbus协议,后续报文长度5个字节,站址1,PDU解析见上节。
6、Modbus_rtu ADU解析
Modbus_rtu报文在modbus通用PDU前添加一个字节的地址域,在PDU后添加两个字节的CRC校验。
请求ADU:01 03 00 00 00 04 44 09
01 03 00 00 00 04 44 09
站址 MODBUS PDU CRC校验
报文:请求设备的数据,站址1,校验码0x44 0x09,PDU解析见上节。
响应ADU:01 03 08 00 22 02 64 00 25 00 4A 77 C3
01 03 08 00 22 02 64 00 25 00 4A 77C3
站址 MODBUS PDU CRC校验
报文:接收设备的数据,站址1,校验码0x77 0xC3,PDU解析见上节。
7、MODBUS异常响应解析
当客户机设备向服务器设备发送请求时,客户机希望一个正常响应。从主站询问中出现下列四种可能事件之一:
1.如果服务器设备接收到无通信错误的请求,并且可以正常地处理询问,那么服务器设备将返回一个正常响应。
2.如果由于通信错误,服务器没有接收到请求,那么不能返回响应。客户机程序将最终处理请求的超时状态。
3.如果服务器接收到请求,但是检测到一个通信错误(奇偶校验、LRC、CRC、…),那么不能返回响应。客户机程序将最终处理请求的超时状态。
4.如果服务器接收到无通信错误的请求,但不能处理这个请求(例如,如果请求读一个不存在的输出或寄存器),服务器将返回一个异常响应,通知用户错误的本质特性。
异常响应报文有两个与正常响应不同的域:
功能码域:在正常响应中,服务器利用响应功能码域来应答最初请求的功能码。所有功能码的最高有效位(MSB)都为 0(它们的值都低于十六进制 80) 。在异常响应中,服务器设置功能码的MSB 为 1。这使得异常响应中的功能码值比正常响应中的功能码值高十六进制80。
通过设置功能码的MSB,客户机的应用程序能够识别异常响应, 并且能够检测异常码的数据域。
数据域:在正常响应中,服务器可以返回数据域中数据或统计表(请求中要求的任何报文)。在异常响应中,服务器返回数据域中的异常码。这就定义了产生异常的服务器状态。
请求PDU:01 04 A1 00 06
01 04A1 00 06
功能码 线圈地址 读取线圈个数
报文:请求设备数据,PDU解析见上节。
响应PDU:81 02
81 02
异常响应功能码 异常码
报文:异常响应报文,异常原因:非法数据地址。
8、Modbus常见异常码一览
MODBUS异常码 | ||
---|---|---|
异常码 | 名称 | 含义 |
01 | 非法功能 | 对于服务器(或从站)来说,询问中接收到的功能码是不可允许的操作。这也许是因为功能码仅仅适用于新设备而在被选单元中是不可实现的。同时,还指出服务器(或从站)在错误状态中处理这种请求,例如:因为它是未配置的,并且要求返回寄存器值。 |
02 | 非法数据地址 | 对于服务器(或从站)来说,询问中接收到的数据地址是不可允许的地址。特别是,参考号和传输长度的组合是无效的。对于带有100个寄存器的控制器来说,带有偏移量96和长度4的请求会成功,带有偏移量96和长度5的请求将产生异常码 02。 |
03 | 非法数据值 | 对于服务器(或从站)来说,询问中包括的值是不可允许的值。这个值指示了组合请求剩余结构中的故障,例如:隐含长度是不确的。并不意味着,因为MODBUS 协议不知道任何特殊寄存器的任何特殊值的重要意义,寄存器中被提交存储的数据项有一个应用程序期望之外的值。 |
04 | 从站设备故障 | 当服务器(或从站)正在设法执行请求的操作时,产生不可重新获得的差错。 |
05 | 确认 | 与编程命令一起使用。 服务器(或从站)已经接受请求,并切正在处理这个请求,但是需要长的持续时间进行这些操作。返回这个响应防止在客户机(或主站)中发生超时错误。客户机(或主站)可以继续发送轮询程序完成报文来确定是否完成处理。 |
06 | 从属设备忙 | 与编程命令一起使用。服务器(或从站)正在处理长持续时间的程序命令。张服务器(或从站)空闲时,用户(或主站)应该稍后重新传输报文。 |
08 | 存储奇偶性差错 | 与功能码20和21以及参考类型6一起使用,指示扩展文件区不能通过一致性校验。服务器(或从站)设法读取记录文件,但是在存储器中发现一个奇偶校验错误。客户机(或主方)可以重新发送请求,但可以在服务器(或从站)设备上要求服务。 |
0A | 不可用网关路径 | 与网关一起使用,指示网关不能为处理请求分配输入端口至输出端口的内部通信路径。通常意味着网关是错误配置的或过载的。 |
0B | 网关目标设备响应失败 | 与网关一起使用,指示没有从目标设备中获得响应。通常意味着设备未在网络中。 |