在Modbus主站与从站之间进行大数据量通信的方法

什么是Modbus协议?

Modbus是使用主从关系实现的请求 - 响应协议。 在主从关系中,通信总是成对发生 —— 一个设备必须发起请求,然后等待响应 , 并且发起设备(主设备)负责发起每次交互。 通常,主设备是人机界面(HMI)或监控和数据采集(SCADA)系统,从设备是传感器、可编程逻辑控制器(PLC)或可编程自动化控制器(PAC)。 这些请求和响应的内容以及发送这些消息的网络层由协议的不同层来定义。


modbus python 主站 从站 modbus主站和从站_Modbus通信

图1. 主从网络关系

Modbus协议层

在最初的做法中,Modbus是建立在串行端口之上的单一协议,因此它不能被分成多个层。 随着时间的推移,该协议引入了不同的应用程序数据单元来更改串行通信使用的数据包格式,或允许使用TCP/IP和用户数据报协议(UDP)网络。 这实现了定义协议数据单元(PDU)的核心协议和定义应用数据单元(ADU)的网络层的分离。

协议数据单元(PDU)

PDU及其处理代码构成了Modbus应用协议规范的核心。 该规范定义了PDU的格式、协议使用的各种数据概念、如何使用功能代码访问数据,以及每个功能代码的具体实现和限制。

Modbus PDU格式被定义为一个功能代码,后面跟着一组关联的数据。 该数据的大小和内容由功能代码定义,整个PDU(功能代码和数据)的大小不能超过253个字节。 每个功能代码都有一个特定的行为,从设备可以根据所需的应用程序行为灵活地实现这些行为。 PDU规范定义了数据访问和操作的核心概念;但是,从设备可能会以规范中未明确定义的方式处理数据。

访问Modbus和Modbus数据模型中的数据

通常,Modbus可访问的数据存储在四个数据库或地址范围的其中一个: 线圈状态、离散量输入、保持寄存器和输入寄存器。 与许多规范一样,名称可能因行业或应用而异。 例如,保持寄存器也可以称为输出寄存器,线圈状态可能称为数字或离散量输出。 这些数据库定义了所包含数据的类型和访问权限。 从设备可以直接访问这些数据,因为这些数据由设备本地托管。 Modbus可访问的数据通常是设备主存的一个子集。 相反,Modbus主设备必须通过各种功能代码请求访问这些数据。

表1中描述了每个区块的行为。

表1. Modbus 数据模型区块

内存区块

数据类型

主设备访问

从设备访问

线圈状态

布尔

读/写

读/写

离散输入

布尔

只读

读/写

保持寄存器

无符号双字节整型

读/写

读/写

输入寄存器

无符号双字节整型

只读

读/写

这些区块允许您限制或允许访问不同的数据元素,并且为应用层提供简化的机制来访问不同的数据类型。

这些区块是完全概念性的。 它们可能作为独立的内存地址存在于给定的系统中,但也可能重叠。 例如,线圈状态1可能存在于与保持寄存器1所代表的字的第一位相同的内存中。 寻址方案完全由从设备定义,其对每个内存区的解释是设备数据模型的重要组成部分。

数据模型寻址

该规范将每个区块定义为包含多达65,536(2^16)个元素的地址空间。 在PDU的定义中,Modbus定义了每个数据元素的地址,范围从0到65,535。但是,每个数据元素的编号从1到n,其中n的最大值为65,536。也就是说,线圈状态1位于地址0的线圈状态区块中,而保持寄存器54位于从机被定义为保持寄存器的内存部分中的地址53。

规范允许的全部范围不需要给定设备实现。 例如,设备可能会选择不执行线圈、离散输入或输入寄存器,而只使用保持寄存器150至175和200至225。这是完全可以接受的,并且通过例外来处理无效的访问尝试。

数据寻址范围

虽然规范将不同的数据类型定义为存在于不同的区块中,并为每种类型分配一个本地地址范围,但这并不一定会转化为用于记录或理解给定设备的Modbus可访问内存的直观编址方案。 为了简化对内存区块位置的理解,引入了一种编号方案,其将前缀添加到所讨论的数据的地址中。

例如,设备手册不会引用地址13寄存器14的数据项,而是引用地址4,014,40,014或400,014的数据项。在任何情况下,第一个数字都是4,表示保持寄存器,剩余数字则表示指定地址。 4XXX、4XXXX和4XXXXX的区别取决于设备使用的地址空间。 如果所有65,536个寄存器都在使用中,应该使用4XXXXX符号,因为其允许范围为400,001~465,536。如果只使用几个寄存器,通常的做法是使用范围4,001到4,999。

在这种寻址方案中,每种数据类型都被分配了一个前缀,如表2所示。

表2. 数据范围前缀

数据区块

前缀

线圈状态

0

离散输入

1

输入寄存器

3

保持寄存器

4

线圈状态存在前缀为0的情况。这意味着4001的引用可能指的是保持寄存器1或线圈4001。因此,建议所有新寻址方案都采用带前导零的6位寻址,并在文档中进行标注。 因此,保持寄存器1的地址为400,001,而线圈4001的地址则为004,001。

数据地址起始值

内存地址和参考数字之间的差异会由给定应用程序选择的索引进一步复杂化。 如前所述,保存寄存器1位于地址零。 通常,参考号码是1索引,这意味着给定范围的起始值为1。 因此,400,001就表示为地址0的保持寄存器00001。一些做法选择以零开始其范围,这意味着400,000转换为地址零的保持寄存器。 表3展示了这个概念。

表3. 寄存器索引方案

地址

寄存器编号

编号1(1索引,标准)

编号(0索引,替换)

0

1

400 001

400 000

1

2

400 002

400 001

2

3

400 003

400 002

 1索引范围应用较为广泛,强烈建议采用。 无论哪种情况,每个范围的起始值都应在文档中注明。

大数据类型

Modbus标准提供了一个相对简单的数据模型,它不包含无符号字和位值之外的其他数据类型。 如果系统的位值对应于螺线管和继电器,并且字值对应于未缩放的ADC值,这是足够的,但对于更高级的系统则可能不足。 因此,许多Modbus实现都包含跨寄存器边界的数据类型。例如,存储在保持寄存器中的字符串遵循标准格式(400,001),但后跟一个十进制数、长度和字符串的字节顺序(400,001.2H是指保持寄存器1中的两个字符串,其中高位字节对应到字符串的第一个字符)。 这是必需的,因为每个请求的大小都是有限的,所以Modbus主机必须知道字符串的确切范围,而不是像NULL那样搜索长度或分隔符。

位访问

除了允许访问跨寄存器边界的数据之外,一些Modbus主设备还支持对寄存器中各个位的引用。 这是有好处的,因为它允许设备将相同内存范围内的每种类型的数据组合在一起,而不必将二进制数据分成线圈整体和离散量输入范围。 这通常使用小数点和位索引或数字进行索引,具体取决于如何实现。 也就是说,第一个寄存器的第一位可能是400,001.00或400,001.01。 建议任何文档都要说明所使用的索引方案。

数据字节顺序

多寄存器数据(单精度浮点值),可以通过将数据拆分到两个寄存器,轻松地在Modbus中传输。 由于这不是由标准定义的,因此分割的字节顺序没有规定。 尽管每个无符号字必须以网络(big-endian)字节顺序发送以满足标准,但许多设备会颠倒多字节数据的字节顺序。 图2所示的是一个不常见但有效的例子。


一种在Modbus主站和从站间进行大数据量通信的方法,包括以下步骤:

步骤一:Modbus主站发送Modbus请求报文。该Modbus请求报文的数据域包括帧类型、数据类型、起始地址和数据量四个位场;

步骤二:Modbus从站接收到该Modbus请求报文,根据该Modbus请求报文中指定的数据类型、起始地址和数据量,从内存中取出数据;

步骤三:Modbus从站将该数据分段封装到Modbus响应报文里,形成分段响应报文,并依次连续发送该分段响应报文。该Modbus响应报文的数据域包括帧类型、数据类型、分段协议、有效数据数量和有效数据五个位场;

步骤四:Modbus主站接收该分段响应报文,判断其是否有分段帧错误或遗失,如果是,则执行步骤五,否则执行步骤七;

步骤五:Modbus主站根据分段协议计算错误或丢失的分段帧中有效数据的地址和长度,重新发送对该有效数据的请求报文;

步骤六:Modbus从站返回响应报文;

步骤七:本次数据通信过程结束。

Modbus总线由于其协议开放、实施简便、可靠性高的特点,已经成为一种事实上的工业标准,得到了众多厂商的产品支持。目前已经安装的Modbus节点超过1000万个。随着信息技术的不断发展,许多应用场合要求使用现有的Modbus设备进行大数据量通信,如电力通信领域一次传输的故障波形记录可能达到数十MB,视频监控领域一次传输的图像数据可能达到数百MB。Modbus协议中定义的数据模型仅支持最多65536个数据寻址,对“输入寄存器”类型数据,最大只能寻址131.072KB数据容量。在进行大数据量通信时,从站设备地址空间不足。

Modbus早期在串行链路上执行的长度约束限制了其ADU (应用数据单元)的大小,一帧Modbus报文最大长度为256字节。使用Modbus协议中已经定义的公共功能码进行通信时,主站(作为客户机)和从站(作为服务器)之间按照“请求--应答”格式交换信息。在进行大数据量通信时,需要主站多次请求,从站多次应答,通信效率较低。