Modbus是一种串行通信协议,最初由Modicon公司(现为施耐德电气的一部分)在1979年为使用其PLC(可编程逻辑控制器)而开发。Modbus已成为工业领域内广泛使用的一种通信协议,特别是对于监控和控制系统。Modbus协议支持多种通信方式,包括RTU(Remote Terminal Unit,远程终端单元模式)、TCP/IP和ASCII(美国标准信息交换码)等。
本文主要介绍Modbus RTU、Modbus TCP和Modbus ASCII的报文结构。
Modbus RTU(Remote Terminal Unit)是一种在串行通讯中广泛使用的协议,主要应用于工业领域的设备之间。这个协议是基于主/从(或客户端/服务器)架构,允许主机(通常称为Master)与多个从机(通常称为Slave)进行通信。在Modbus RTU协议中,数据通过二进制形式传输,使得通信更加高效。
一个典型的Modbus RTU报文结构如下:
用途 | 设备地址 | 功能码 | 数据 | CRC校验 |
---|---|---|---|---|
长度 | 8bit | 8bit | 可变(0到252个8bit) | 16bit |
描述 | 每个从机都有一个唯一的地址。地址范围从0到247。地址0是广播地址,向所有从机发送消息,但从机不会对广播信息进行应答。 | 用于指定主机要求从机执行的操作类型 | 数据部分的长度可变,包含了命令的具体参数,确切格式和长度取决于功能码。 | 用于检查数据在传输过程中是否有错误。 |
在 Modbus 标准协议中,功能码总共分为三类:公用功能码、自定义功能码、保留功能码。
(公用功能码和自定义功能码的区别可以近似对比计算机的熟知端口和注册端口)
数据部分主要包含了命令的具体内容,它的结构和长度依赖于功能码的不同。本文仅列举几个常见的功能码,以及与之对应的数据部分的结构和作用:
主机发送数据部分:
主机发送功能码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 |
功能码06主机发送的数据和从机回复的数据相同。
如主机想给0x0032的寄存器中写入0x0001,则数据为:
用途 | 寄存器地址-高 | 寄存器地址-低 | 写入数据-高 | 写入数据-低 |
---|---|---|---|---|
长度 | 8bit | 8bit | 8bit | 8bit |
举例 | 0x00 | 0x32 | 0x00 | 0x01 |
主机发送数据部分:从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 |
通常Modbus的通讯中可能存在三类异常情况:
用途 | 异常码 |
---|---|
长度 | 8bit |
举例 | 0x04 |
常见异常码如下: |
异常码 | 名称 | 产生原因 |
---|---|---|
01 (0x01) | 非法功能码 | 从机不支持功能码。 |
02 (0x02) | 非法数据地址 | 从机中无对应寄存器。 |
03 (0x03) | 非法数据值 | 数据超出可用范围或数据不可用 |
04 (0x04) | 从机故障 | 从机出现未知错误 |
05 (0x05) | 确认 | 从机已接受命令,正在处理,用于避免发生超时错误 |
06 (0x06) | 从机忙 | 从机设备正在处理长时间命令 |
07 (0x07) | 否定确认 | 从机无法执行主机命令 |
08 (0x08) | 存储奇偶性差错 | 扩展文件区不能通过一致性校验 |
Modbus RTU协议中常用的CRC校验采用的是CRC-16算法,具体的多项式为0x8005(或其二进制形式1000 0000 0000 0101),初始值为0xFFFF。
CRC校验的基本步骤如下:
当接收方收到报文时,会对整个报文(包括CRC校验码)使用相同的CRC计算流程。如果报文未被篡改,计算结果应为0x0000(考虑到了CRC码的加入和计算规则)。如果结果不是0x0000,则表明报文在传输过程中可能遭到了篡改或出现了错误。
Modbus TCP 是基于Modbus RTU协议的扩展,它是一种在以太网上使用的通讯协议。Modbus TCP 报文格式相较于Modbus RTU,主要是在报文的前面增加了一个MBAP头(Modbus Application Protocol header),用于在TCP/IP网络中传输。
用途 | 事务标识符 | 协议标识符 | 长度字段 | 单元标识符 | *功能码 | 数据 |
---|---|---|---|---|---|---|
长度 | 16bit | 16bit | 16bit | 8bit | 8 | 可变(0到252个8bit) |
描述 | 用于标识请求和响应的对应关系,客户端发起的每个请求都会分配一个唯一的事务标识符,服务器在响应时会使用相同的标识符。 | 用于识别上层协议,固定为0x0000。 | 表示接下来的单元标识符、功能码和数据的总长度,单位为字节。 | 用于在连接到Modbus网关时识别远程服务器上的从 用于指定主机要求从机从机操作类型 类型 | 数据部分的长度可变,包含了命令的具体参数,确切格式和长度取决于功能码。 |
事务标识符、协议标识符、长度字段、单元标识符四部分即为MBAP头。
表示接下来的单元标识符、功能码和数据的总长度,单位为字节。如字段长度为0x0008,则后续部分长度为8字节。
同Modbus RTU相同
同Modbus RTU相同
Modbus ASCII(美国标准信息交换码)报文格式是Modbus协议的一种变体,它允许设备通过文本可读的格式进行通信。这种格式特别适用于速度不是非常关键的应用场景和那些需要通过人眼检查数据的场合。
用途 | 起始符 | 设备地址 | 功能码 | 数据 | 校验和 | 结束符 |
---|---|---|---|---|---|---|
长度 | 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码 | 用于错误检测 | 标记数据传输的结束 |
每条Modbus ASCII消息的开头都会有这样一个冒号,用来告诉接收设备一条新的消息正在开始。
由于Modbus ASCII中的每个字节都用两个ASCII字符表示,设备地址也不例外。例如,如果设备地址是17(十进制),它将被转换为十六进制11,然后在ASCII消息中表示为两个字符“11”。
同Modbus RTU相同,即用ASCII字符来展示功能码的十六进制数。
同Modbus RTU相同,即用ASCII字符来展示功能码的十六进制数。
Modbus ASCII使用一种简单的校验和机制,称为LRC(Longitudinal Redundancy Check,纵向冗余校验)。LRC的目的是确保数据在传输过程中的完整性和准确性。LRC校验和是通过对消息中所有字符的ASCII值进行计算得到的。
LRC计算步骤如下:
在Modbus ASCII模式下,每条消息的结束符由两个字符组成:CR (Carriage Return) 和 LF (Line Feed)。在ASCII编码中,CR的十六进制值是0x0D,LF的十六进制值是0x0A。因此,每条Modbus ASCII消息的末尾都会有这样一个字符序列:0x0D0x0A。
在Modbus ASCII协议中,组合使用CR和LF作为消息结束符,可以确保无论在哪种操作系统上,接收设备都能正确地识别出消息的结束,从而进行相应的处理。
上一篇:SQL-窗口函数