Modbus报文详解
Modbus是一种串行通信协议,最初由Modicon公司(现为施耐德电气的一部分)在1979年为使用其PLC(可编程逻辑控制器)而开发。Modbus已成为工业领域内广泛使用的一种通信协议,特别是对于监控和控制系统。Modbus协议支持多种通信方式,包括RTU(Remote Terminal Unit,远程终端单元模式)、TCP/IP和ASCII(美国标准信息交换码)等。
本文主要介绍Modbus RTU、Modbus TCP和Modbus ASCII的报文结构。
1.Modbus RTU
1.1简介
Modbus RTU(Remote Terminal Unit)是一种在串行通讯中广泛使用的协议,主要应用于工业领域的设备之间。这个协议是基于主/从(或客户端/服务器)架构,允许主机(通常称为Master)与多个从机(通常称为Slave)进行通信。在Modbus RTU协议中,数据通过二进制形式传输,使得通信更加高效。
1.2报文格式
一个典型的Modbus RTU报文结构如下:
用途 | 设备地址 | 功能码 | 数据 | CRC校验 |
---|---|---|---|---|
长度 | 8bit | 8bit | 可变(0到252个8bit) | 16bit |
描述 | 每个从机都有一个唯一的地址。地址范围从0到247。地址0是广播地址,向所有从机发送消息,但从机不会对广播信息进行应答。 | 用于指定主机要求从机执行的操作类型 | 数据部分的长度可变,包含了命令的具体参数,确切格式和长度取决于功能码。 | 用于检查数据在传输过程中是否有错误。 |
1.3报文详解
1.3.1设备地址
1.3.1.1地址范围
- 在Modbus RTU中,每个从机被分配一个唯一的地址,用于在网络上标识。
- 这个地址是一个8位的数值,范围从0到247。
- 通常情况下,地址0是保留的,用于广播命令,即发送给网络上所有设备的命令。
- 地址248到255通常是保留给特殊功能或未来使用的。
1.3.1.2地址配置
- 设备地址通常需要在设备接入Modbus网络之前就进行配置。
- 不同的设备制造商可能会提供不同的方法来设置这些地址,例如通过拨码开关、软件界面或者直接通过Modbus命令。
1.3.1.3通信过程
- 当主机向从机发送命令时,主机会在消息的开始部分包含从机的地址。从机收到消息后,会先检查消息地址,如果消息是发给自己的,则会执行,否则会抛弃。
- 对广播地址(0),所有设备都会执行该命令。
1.3.1.4地址冲突
- 如果两个或更多的设备被设置成相同的地址,会导致地址冲突,进而导致通信失败。
1.3.2 功能码
在 Modbus 标准协议中,功能码总共分为三类:公用功能码、自定义功能码、保留功能码。
- 公用功能码即经过Modbus协会确认,并提供了公开文档的功能码。在文档中被明确定义,确保唯一。
- 自定义功能码为各厂家(用户)自定义的功能码,不保证唯一性。
- 保留功能码是在报文格式不给范的时候使用的一些功能码,现在已经不作为公共使用了。
(公用功能码和自定义功能码的区别可以近似对比计算机的熟知端口和注册端口)
1.3.2.1 读取功能码
- 01 (0x01): 读线圈状态(Read Coils)- 用于读取一组逻辑线圈的当前状态(ON/OFF)。
- 02 (0x02): 读离散输入状态(Read Discrete Inputs)- 用于读取一组离散输入的状态(ON/OFF)。
- 03 (0x03): 读保持寄存器(Read Holding Registers)- 用于读取一组保持寄存器中的二进制内容。
- 04 (0x04): 读输入寄存器(Read Input Registers)- 用于读取一组输入寄存器中的二进制内容。
1.3.2.2 写入功能码
- 05 (0x05): 写单个线圈(Write Single Coil)- 用于写入单个逻辑线圈的状态(ON/OFF)。
- 06 (0x06): 写单个寄存器(Write Single Register)- 用于写入单个保持寄存器的数据。
- 15 (0x0F): 写多个线圈(Write Multiple Coils)- 用于写入一组逻辑线圈的状态。
- 16 (0x10): 写多个寄存器(Write Multiple Registers)- 用于写入一组保持寄存器的数据。
1.3.2.3 诊断功能码
- 08 (0x08): 诊断(Diagnostic)- 这组功能码用于诊断通信链路的状态,以及测试和诊断Modbus设备。
1.3.2.4 特殊功能码
- 17 (0x11): 报告从机ID(Report Slave ID)- 返回关于设备的信息,如运行状态和识别信息。
- 22 (0x16): 屏蔽写寄存器(Mask Write Register)- 允许用户修改保持寄存器的内容,而不改变未指定位的内容。
- 23 (0x17): 读/写多个寄存器(Read/Write Multiple Registers)- 同时进行读取和写入操作。
1.3.2.5 异常码
- 异常功能码:异常功能码为正常功能码 + 0x80,如写入单个寄存器错误返回异常码为0x86。
1.3.3 数据
数据部分主要包含了命令的具体内容,它的结构和长度依赖于功能码的不同。本文仅列举几个常见的功能码,以及与之对应的数据部分的结构和作用:
1.3.3.1 读取保持寄存器 (功能码03)
主机发送数据部分:
主机发送功能码03的数据,表示要读取从0x0032开始3个寄存器的内容。
用途 | 寄存器起始地址-高 | 寄存器起始地址-低 | 寄存器数量-高 | 寄存器数量-低 |
---|---|---|---|---|
长度 | 8bit | 8bit | 8bit | 8bit |
举例 | 0x00 | 0x32 | 0x00 | 0x03 |
从机回复的数据部分: | ||||
从机发送功能码03的数据,表示读取到的数据总共6个字节,分别为0x00、0x01、0x00、0x02、0x00、0x03,即读取到的3个寄存器的数据为0x0001、0x0002、0x0003。 |
用途 | 返回字节数 | 寄存器1数据-高 | 寄存器1数据-低 | 寄存器2数据-高 | 寄存器2数据-低 | 寄存器3数据-高 | 寄存器3数据-低 |
---|---|---|---|---|---|---|---|
长度 | 8bit | 8bit | 8bit | 8bit | 8bit | 8bit | 8bit |
举例 | 0x06 | 0x00 | 0x01 | 0x00 | 0x02 | 0x00 | 0x03 |
1.3.3.2 写单个寄存器 (功能码06)
功能码06主机发送的数据和从机回复的数据相同。
如主机想给0x0032的寄存器中写入0x0001,则数据为:
用途 | 寄存器地址-高 | 寄存器地址-低 | 写入数据-高 | 写入数据-低 |
---|---|---|---|---|
长度 | 8bit | 8bit | 8bit | 8bit |
举例 | 0x00 | 0x32 | 0x00 | 0x01 |
1.3.3.3 写多个寄存器 (功能码16)
主机发送数据部分:从0x0032寄存器开始,连续3个寄存器,写入数据分别为0x0001、0x0002、0x0003。
用途 | 寄存器起始地址-高 | 寄存器起始地址-低 | 寄存器数量-高 | 寄存器数量-低 | 寄存器1数据-高 | 寄存器1数据-低 | 寄存器2数据-高 | 寄存器2数据-低 | 寄存器3数据-高 | 寄存器3数据-低 |
---|---|---|---|---|---|---|---|---|---|---|
长度 | 8bit | 8bit | 8bit | 8bit | 8bit | 8bit | 8bit | 8bit | 8bit | 8bit |
举例 | 0x00 | 0x32 | 0x00 | 0x03 | 0x00 | 0x01 | 0x00 | 0x02 | 0x00 | 0x03 |
从机回复数据部分:从0x0032寄存器开始,写入数据到连续3个寄存器。
用途 | 寄存器起始地址-高 | 寄存器起始地址-低 | 寄存器数量-高 | 寄存器数量-低 |
---|---|---|---|---|
长度 | 8bit | 8bit | 8bit | 8bit |
举例 | 0x00 | 0x32 | 0x00 | 0x03 |
1.3.3.4 异常数据(异常功能码)
通常Modbus的通讯中可能存在三类异常情况:
- 1.因为通讯故障之类的原因,从机没有收到主机发出的信息,则主机将按照超时进行处理。
- 2.从机收到了报文,但是报文错误(CRC校验不通过),从机将丢弃报文,主机将按照超时进行处理。
- 3.从机接收到了报文,但是报文要求的操作无法实现(如功能码不存在、寄存器范围不对等),从机将会返回包含异常码的响应报文。
用途 | 异常码 |
---|---|
长度 | 8bit |
举例 | 0x04 |
常见异常码如下: |
异常码 | 名称 | 产生原因 |
---|---|---|
01 (0x01) | 非法功能码 | 从机不支持功能码。 |
02 (0x02) | 非法数据地址 | 从机中无对应寄存器。 |
03 (0x03) | 非法数据值 | 数据超出可用范围或数据不可用 |
04 (0x04) | 从机故障 | 从机出现未知错误 |
05 (0x05) | 确认 | 从机已接受命令,正在处理,用于避免发生超时错误 |
06 (0x06) | 从机忙 | 从机设备正在处理长时间命令 |
07 (0x07) | 否定确认 | 从机无法执行主机命令 |
08 (0x08) | 存储奇偶性差错 | 扩展文件区不能通过一致性校验 |
1.3.4 CRC校验
Modbus RTU协议中常用的CRC校验采用的是CRC-16算法,具体的多项式为0x8005
(或其二进制形式1000 0000 0000 0101
),初始值为0xFFFF
。
CRC校验的基本步骤如下:
- 预置:CRC寄存器预置为
0xFFFF
。 - 数据输入:报文中除了CRC校验码以外的所有字节(包括设备地址、功能码和数据)按照顺序进行处理。
- 计算:对每一个字节,从最高位到最低位,将其与CRC寄存器当前的值进行异或运算。如果结果的最高位为1,则将寄存器的值左移一位并与
0x8005
进行异或运算;如果最高位为0,则只需左移一位。重复此过程,直至8位都处理完毕。然后继续处理下一个字节,直到所有字节都计算完毕。 - 结果:最后CRC寄存器中的值就是CRC校验码,通常在传输前转换为低字节在前(Little-Endian)的形式,并附加到报文的末尾。
当接收方收到报文时,会对整个报文(包括CRC校验码)使用相同的CRC计算流程。如果报文未被篡改,计算结果应为0x0000
(考虑到了CRC码的加入和计算规则)。如果结果不是0x0000
,则表明报文在传输过程中可能遭到了篡改或出现了错误。
2.Modbus TCP
2.1 简介
Modbus TCP 是基于Modbus RTU协议的扩展,它是一种在以太网上使用的通讯协议。Modbus TCP 报文格式相较于Modbus RTU,主要是在报文的前面增加了一个MBAP头(Modbus Application Protocol header),用于在TCP/IP网络中传输。
2.2 报文格式
用途 | 事务标识符 | 协议标识符 | 长度字段 | 单元标识符 | *功能码 | 数据 |
---|---|---|---|---|---|---|
长度 | 16bit | 16bit | 16bit | 8bit | 8 | 可变(0到252个8bit) |
描述 | 用于标识请求和响应的对应关系,客户端发起的每个请求都会分配一个唯一的事务标识符,服务器在响应时会使用相同的标识符。 | 用于识别上层协议,固定为0x0000。 | 表示接下来的单元标识符、功能码和数据的总长度,单位为字节。 | 用于在连接到Modbus网关时识别远程服务器上的从 用于指定主机要求从机从机操作类型 类型 | 数据部分的长度可变,包含了命令的具体参数,确切格式和长度取决于功能码。 |
事务标识符、协议标识符、长度字段、单元标识符四部分即为MBAP头。
2.3 报文详解
2.3.1 事务标识符
- 用于标识请求和响应的对应关系,客户端发起的每个请求都会分配一个唯一的事务标识符,服务器在响应时会使用相同的标识符。在并发请求的环境下,事务标识符尤其重要。
- 事务标识符通常由请求发起端生成,通过递增、随机等不同方式进行生成。
2.3.2 协议标识符
- 协议标识符用于识别上层协议。在标准的Modbus TCP应用中,这个值被设置为0x0000,表示使用的是Modbus协议。
- 虽然协议标识符通常被设置为0,但它的存在为Modbus TCP提供了扩展的可能性。这意味着在未来,如果需要,Modbus TCP可以支持除了Modbus之外的其他协议,而无需更改现有的架构。
2.3.3 长度字段
表示接下来的单元标识符、功能码和数据的总长度,单位为字节。如字段长度为0x0008,则后续部分长度为8字节。
2.3.4 单元标识符
- 在纯Modbus TCP网络中,单元标识符通常被设置为0或255。这是因为在这样的环境里,IP地址已经足够用来区分不同的设备,单元标识符并不起到区分设备的作用。
- Modbus TCP到RTU/ASCII网关中,一个Modbus TCP请求通过网络发送到一个网关设备,然后网关设备将这个请求转换为Modbus RTU或ASCII格式,并通过串行通信发送给指定的从机。在这种情况下,单元标识符就是用来告诉网关这个请求应该转发给哪个从机的。
2.3.5 功能码
同Modbus RTU相同
2.3.6 数据
同Modbus RTU相同
3. Modbus ASCII
3.1简介
Modbus ASCII(美国标准信息交换码)报文格式是Modbus协议的一种变体,它允许设备通过文本可读的格式进行通信。这种格式特别适用于速度不是非常关键的应用场景和那些需要通过人眼检查数据的场合。
3.2 报文格式
用途 | 起始符 | 设备地址 | 功能码 | 数据 | 校验和 | 结束符 |
---|---|---|---|---|---|---|
长度 | 1个ASCII字符 | 2个ASCII字符 | 2个ASCII字符 | 可变(0-504个ASCII字符,应为偶数个) | 2个ASCII字符 | 2个ASCII字符 |
描述 | 以冒号(":")字符开始,用ASCII码表示为0x3A | 每个从机都有一个唯一的地址。地址范围从0到247。地址0是广播地址,向所有从机发送消息,但从机不会对广播信息进行应答。 | 用于指定主机要求从机执行的操作类型 | 数据部分的长度可变,包含了命令的具体参数,确切格式和长度取决于功能码。 | 用于检查数据在传输过程中是否有错误。 | 每个报文以回车和换行字符(CR LF,ASCII码为0x0D和0x0A)结束 |
ASCII模式下每个字符占用10bit,每个字符格式为: |
用途 | 起始位 | 数据位 | 奇偶校验 | 停止位 |
---|---|---|---|---|
长度 | 1bit | 7bit | 1bit | 1bit |
备注 | 标记数据传输的开始 | 实际的数据内容,即显示的ASCII码 | 用于错误检测 | 标记数据传输的结束 |
3.3 报文详解
3.3.1 起始符
每条Modbus ASCII消息的开头都会有这样一个冒号,用来告诉接收设备一条新的消息正在开始。
3.3.2 设备地址
由于Modbus ASCII中的每个字节都用两个ASCII字符表示,设备地址也不例外。例如,如果设备地址是17(十进制),它将被转换为十六进制11,然后在ASCII消息中表示为两个字符“11”。
3.3.3 功能码
同Modbus RTU相同,即用ASCII字符来展示功能码的十六进制数。
3.3.4 数据
同Modbus RTU相同,即用ASCII字符来展示功能码的十六进制数。
3.3.5 校验和
Modbus ASCII使用一种简单的校验和机制,称为LRC(Longitudinal Redundancy Check,纵向冗余校验)。LRC的目的是确保数据在传输过程中的完整性和准确性。LRC校验和是通过对消息中所有字符的ASCII值进行计算得到的。
LRC计算步骤如下:
- 初始化LRC:LRC的初始值为0x00。
- 计算校验和:将消息中除了起始冒号和结束的回车换行符之外的所有字符(实际上是它们的ASCII值)两两一组(因为Modbus ASCII将每个字节分为两个ASCII字符来表示),转换为字节(即,将ASCII字符对应的十六进制数转换为字节),然后累加到LRC中。这个过程中如果累加结果超过了一个字节的表示范围(即超过了0xFF),则只保留结果的低8位。
- 取反加一:累加完成后,将LRC的值取反(即0xFF - LRC),然后加1。这样得到的最终结果就是发送消息时附加的LRC校验和。
- 发送消息时的处理:计算出的LRC校验和需要被转换为两个ASCII字符附加在消息的末尾,紧接着是结束的回车换行符。这样,接收方在接收到消息后,可以使用同样的方法计算校验和,并与接收到的校验和进行比较,以验证数据的完整性和准确性。
3.3.6 结束符
在Modbus ASCII模式下,每条消息的结束符由两个字符组成:CR (Carriage Return) 和 LF (Line Feed)。在ASCII编码中,CR的十六进制值是0x0D,LF的十六进制值是0x0A。因此,每条Modbus ASCII消息的末尾都会有这样一个字符序列:0x0D0x0A。
- CR(Carriage Return,回车):在打字机时代,这个操作会让打字头回到一行的开头。在计算机文本文件中,它的作用依赖于系统,但通常用于表示一行的结束。
- LF(Line Feed,换行):在打字机时代,这个操作会让纸张向上滚动一行。在计算机文本文件中,它通常用来表示新的一行的开始。
在Modbus ASCII协议中,组合使用CR和LF作为消息结束符,可以确保无论在哪种操作系统上,接收设备都能正确地识别出消息的结束,从而进行相应的处理。
Modbus报文详解的更多相关文章
- HTTP权威指南读书笔记(一)HTTP概述、URL和资源及报文详解
一.HTTP概述 1.WEB客户端和服务器. 2.资源:资源可以是各种格式的静态文件,也可以是应用程序. 3.媒体类型 4.URI:统一资源标识符 URL:统一资源定位符. URL的第一部分称为方案: ...
- http协议之报文详解
一. 概述 用于HTTP协议交互的信息被称为HTTP报文.请求端(客户端)的http报文叫做请求报文,响应端的叫做响应报文. 报文,是网络中交换和传输的数据单元,即站点一次性要发送的数据块.报文包含了 ...
- HTTP/1.1报文详解
本文为<三万长文50+趣图带你领悟web编程的内功心法>第三个章节. 3.HTTP/1.1报文详解 在RFC2616中心详细的描述了HTTP/1.1[1]的报文,感兴趣的朋友也可以前往阅读 ...
- ModbusRtu通信报文详解【一】
Modbus协议可谓是工业控制领域应用最广泛的协议之一.根据不同的电气接口,包括Modbus Rtu/ASCII,Modbus TCP/UDP,从学习的角度来说,只要学会其中一种,剩余的都是大同小异的 ...
- 应用层(一)HTTP服务访问基本流程和HTTP报文详解
HTTP属于TCP/IP模型中一个面向文本的应用层协议,所使用的服务器端口号的TCP中的80端口,通信双方在这个基础上进行通信. 每个服务器都有一个应用进程,时刻监听着80端口的用户访问请求.当有用户 ...
- MODBUS协议详解
MODBUS是一个工业上通信常用的通讯协议,一般在PLC上面用的比较多,主要是定义了一种数据传输的规范,比如数据发给谁,数据是干嘛的,数据错没错,接收到数据的从机告诉我数据有没有接受到等. 传输的方式 ...
- Modbus通信协议详解
附:http://www.360doc.com/content/14/0214/13/15800361_352436989.shtml 一.Modbus 协议简介 Modbus 协议是应用于电子控制器 ...
- HTTP请求与响应报文详解
如图所示,这是客户端往服务器发送请求时的报文: 一般来说,将报文分成三个部分,请求行.请求头.请求体 如图,请求行包括三部分内容 1.请求方法,在HTTP里的请求方法种类较多,但就移动端开发来说,常用 ...
- Modbus 通信协议详解
一.Modbus 协议简介 Modbus 协议是应用于电子控制器上的一种通用语言.通过此协议,控制器相互之间.控制器经由网络(例如以太网)和其它设备之间可以通信.它已经成为一通用工业标准.有了 ...
- ModbusRtu通信报文详解【二】
这里接着上一篇内容对ModbusRtu的通信报文做个详细描述: [1]强制单个线圈 功能码:05H [2]预置单个寄存器 功能码:06H [3]强制多个线圈 功能码;0FH [4]预置多个寄存器 功能 ...
随机推荐
- paste命令
paste命令 paste命令会把每个文件以列对列的方式,一列列地加以合并. 语法 paste [OPTION]... [FILE]... 参数 -d, --delimiters=[LIST]: 用指 ...
- java类初始化及代码块加载顺序连根拔起
说明 相信很多人对于java中父子继承关系中,子类实例化调用过程中,代码块的执行顺序都容易忘记或搞混,尤其是java初级笔试题或面试题最容易出这类题目,让人恨得牙痒痒!!! 本文就一次性将其连根铲除, ...
- Oracle Linux6下安装Oracle 12c实战
经过N次安装尝试吐血总结,希望对大家有所帮助,同时做下记录备忘: 总结:安装前的准备工作是关键!!!Check and recheck! 参考:http://docs.oracle.com/cd/E1 ...
- Oracle正则表达式实战
原文链接:http://oracle-base.com/articles/misc/regular-expressions-support-in-oracle.php Introduction Exa ...
- vs 工程中替换 Qt 静态库
上篇介绍了如何编译 Qt 静态库 编译 windows 上的 qt 静态库 这篇介绍如何替换已有的 Qt 静态库,比如 Qt5.15.0 有很多 bug,我们不得不提升 Qt 版本来避免 bug 导致 ...
- [BUUCTF][WEB][极客大挑战 2019]Knife 1
这题几乎是送分 题目不断暗示,后台存在一句话木马 拿个蚁剑连上去就完事了 这里用curl 连上去,演示一下,理解一下其中的原理 #注意 phpinfo() 后面的分号不能省 curl -d " ...
- 关于RabbitMQ消费者预取消息数量参数的合理设置
根据RabbitMQ官方文档描述,可以通过"预取数量"来限制未被确认的消息个数,本质上这也是一种对消费者进行流控的方法. 详见:https://www.rabbitmq.com/c ...
- Linux驱动开发笔记(二):ubuntu系统从源码编译安装gcc7.3.0编译器
前言 编译ubuntu驱动之前,发现使用的gcc是7.3.0,而使用apt管理和下载的都无法直接或间接安装gcc7.3.0,于是只能从源码安装gcc7.3.0编译器. GCC 概述 GCC ...
- sql判断字符串中含中文方法
基于UTF-8字符集 它是一种多字节字符集,编码为变长编码.那么它的编码范围根据:http://www.iteye.com/topic/977671 作者提供的资料学习,整理出它编码范围如下: u2e ...
- Jina AI x 矩池云Matpool |神经搜索引擎,一键构建
图片.视频.语音等非结构化数据在快速增长,随着深度学习技术的不断升级,非结构化数据的搜索也逐渐形成可能.在这样的背景下,专注于神经搜索技术的商业开源软件公司--Jina AI,提出了神经搜索 (Neu ...