Modbus RTU(Remote Terminal Unit)是一种在串行通讯中广泛使用的协议,主要应用于工业领域的设备之间。这个协议是基于主/从(或客户端/服务器)架构,允许主机(通常称为Master)与多个从机(通常称为Slave)进行通信。在Modbus RTU协议中,数据通过二进制形式传输,使得通信更加高效。
一个典型的Modbus RTU报文结构如下:
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地址冲突
- 如果两个或更多的设备被设置成相同的地址,会导致地址冲突,进而导致通信失败。
在 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 读取保持寄存器 (功能码03)
主机发送数据部分:
主机发送功能码03的数据,表示要读取从0x0032开始3个寄存器的内容。
1.3.3.2 写单个寄存器 (功能码06)
1.3.3.3 写多个寄存器 (功能码16)
主机发送数据部分:从0x0032寄存器开始,连续3个寄存器,写入数据分别为0x0001、0x0002、0x0003。
从机回复数据部分:从0x0032寄存器开始,写入数据到连续3个寄存器。
1.3.3.4 异常数据(异常功能码)
通常Modbus的通讯中可能存在三类异常情况:
- 1.因为通讯故障之类的原因,从机没有收到主机发出的信息,则主机将按照超时进行处理。
- 2.从机收到了报文,但是报文错误(CRC校验不通过),从机将丢弃报文,主机将按照超时进行处理。
- 3.从机接收到了报文,但是报文要求的操作无法实现(如功能码不存在、寄存器范围不对等),从机将会返回包含异常码的响应报文。
Modbus RTU协议中常用的CRC校验采用的是CRC-16算法,具体的多项式为(或其二进制形式),初始值为。
CRC校验的基本步骤如下:
- 预置:CRC寄存器预置为。
- 数据输入:报文中除了CRC校验码以外的所有字节(包括设备地址、功能码和数据)按照顺序进行处理。
- 计算:对每一个字节,从最高位到最低位,将其与CRC寄存器当前的值进行异或运算。如果结果的最高位为1,则将寄存器的值左移一位并与进行异或运算;如果最高位为0,则只需左移一位。重复此过程,直至8位都处理完毕。然后继续处理下一个字节,直到所有字节都计算完毕。
- 结果:最后CRC寄存器中的值就是CRC校验码,通常在传输前转换为低字节在前(Little-Endian)的形式,并附加到报文的末尾。
当接收方收到报文时,会对整个报文(包括CRC校验码)使用相同的CRC计算流程。如果报文未被篡改,计算结果应为(考虑到了CRC码的加入和计算规则)。如果结果不是,则表明报文在传输过程中可能遭到了篡改或出现了错误。
Modbus TCP 是基于Modbus RTU协议的扩展,它是一种在以太网上使用的通讯协议。Modbus TCP 报文格式相较于Modbus RTU,主要是在报文的前面增加了一个MBAP头(Modbus Application Protocol header),用于在TCP/IP网络中传输。
事务标识符、协议标识符、长度字段、单元标识符四部分即为MBAP头。
- 用于标识请求和响应的对应关系,客户端发起的每个请求都会分配一个唯一的事务标识符,服务器在响应时会使用相同的标识符。在并发请求的环境下,事务标识符尤其重要。
- 事务标识符通常由请求发起端生成,通过递增、随机等不同方式进行生成。
- 协议标识符用于识别上层协议。在标准的Modbus TCP应用中,这个值被设置为0x0000,表示使用的是Modbus协议。
- 虽然协议标识符通常被设置为0,但它的存在为Modbus TCP提供了扩展的可能性。这意味着在未来,如果需要,Modbus TCP可以支持除了Modbus之外的其他协议,而无需更改现有的架构。
表示接下来的单元标识符、功能码和数据的总长度,单位为字节。如字段长度为0x0008,则后续部分长度为8字节。
- 在纯Modbus TCP网络中,单元标识符通常被设置为0或255。这是因为在这样的环境里,IP地址已经足够用来区分不同的设备,单元标识符并不起到区分设备的作用。
- Modbus TCP到RTU/ASCII网关中,一个Modbus TCP请求通过网络发送到一个网关设备,然后网关设备将这个请求转换为Modbus RTU或ASCII格式,并通过串行通信发送给指定的从机。在这种情况下,单元标识符就是用来告诉网关这个请求应该转发给哪个从机的。
同Modbus RTU相同
同Modbus RTU相同
Modbus ASCII(美国标准信息交换码)报文格式是Modbus协议的一种变体,它允许设备通过文本可读的格式进行通信。这种格式特别适用于速度不是非常关键的应用场景和那些需要通过人眼检查数据的场合。
每条Modbus ASCII消息的开头都会有这样一个冒号,用来告诉接收设备一条新的消息正在开始。
由于Modbus ASCII中的每个字节都用两个ASCII字符表示,设备地址也不例外。例如,如果设备地址是17(十进制),它将被转换为十六进制11,然后在ASCII消息中表示为两个字符“11”。
同Modbus RTU相同,即用ASCII字符来展示功能码的十六进制数。
同Modbus RTU相同,即用ASCII字符来展示功能码的十六进制数。
- 初始化LRC:LRC的初始值为0x00。
- 计算校验和:将消息中除了起始冒号和结束的回车换行符之外的所有字符(实际上是它们的ASCII值)两两一组(因为Modbus ASCII将每个字节分为两个ASCII字符来表示),转换为字节(即,将ASCII字符对应的十六进制数转换为字节),然后累加到LRC中。这个过程中如果累加结果超过了一个字节的表示范围(即超过了0xFF),则只保留结果的低8位。
- 取反加一:累加完成后,将LRC的值取反(即0xFF - LRC),然后加1。这样得到的最终结果就是发送消息时附加的LRC校验和。
- 发送消息时的处理:计算出的LRC校验和需要被转换为两个ASCII字符附加在消息的末尾,紧接着是结束的回车换行符。这样,接收方在接收到消息后,可以使用同样的方法计算校验和,并与接收到的校验和进行比较,以验证数据的完整性和准确性。
在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作为消息结束符,可以确保无论在哪种操作系统上,接收设备都能正确地识别出消息的结束,从而进行相应的处理。
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/bcyy/62834.html