从1开始的索引范围应用较为广泛,强烈建议采用这种方案。无论哪种情况,每个范围的起始值都应在记录时注明。 大数据类型Modbus标准提供了一个相对简单的数据模型,该模型不包含除无符号双字节整型和位值之外的其他数据类型。如果系统的位值对应于螺线管和继电器,并且双字节整型值对应于未缩放的ADC值,上述模型便已足够;但对于更高级的系统,则无法满足需求。因此,许多Modbus实现都包含跨寄存器边界的数据类型。NI LabVIEW数据记录和监控(DSC)模块以及KEPServerEX都定义了许多引用类型。例如,存储在保持寄存器中的字符串应遵循标准格式(400,001),但后跟一个十进制数、长度和字符串的字节序(400,001.2H是指保持寄存器1中包含两个字符的字符串,其中高位字节对应到字符串的第一个字符)。这是必需的,因为每个请求的大小都是有限的,所以Modbus主设备必须知道字符串的确切范围,而不是搜索长度或分隔符(如NULL)。 位访问除了允许访问跨寄存器边界的数据之外,一些Modbus主设备还支持对寄存器中各个位的引用。由于允许设备将相同内存范围内的每种类型的数据组合在一起,而不必将二进制数据分成线圈和离散量输入范围,因此该功能非常有益。通常使用小数点和位索引或编号进行索引,具体取决于如何实现。也就是说,第一个寄存器的第一位可能是400,001.00或400,001.01。建议所有文档均说明所使用的索引方案。 数据字节序通过将数据拆分到两个寄存器,多寄存器数据(如单精度浮点值)可以轻松地通过Modbus进行传输。由于这不是由标准定义的,因此此类拆分的字节序未作规定。尽管每个无符号双字节整型必须以网络(大端)字节序发送才能满足标准,但许多设备会颠倒多字节数据的字节序。图2所示的范例虽然不太常见,但有效地展示了这一观点。 图2.多字数据的字节序交换 主设备需要了解从设备如何将信息存储在内存中,然后才能对其进行正确解码。建议文档写明系统所使用的字序。如果在实现过程中需要更加灵活,也可以将字节序添加为系统配置选项,该选项可提供基础的编码和解码功能。 字符串字符串可以轻松地存储在Modbus寄存器中。为了简单起见,某些实现方法要求字符串长度为2的倍数,并使用空值来填充额外的空间。字节序也是字符串交互中的一个变量。字符串格式可能包含也可能不包含NULL(作为最终值)。举个例子,一些设备的数据存储方法可能如图3所示。 图3.Modbus字符串中的字节序反转 了解功能码数据模型可能因设备而异,但功能码则与之不同,功能码及其数据由标准明确定义。每个功能都遵循一种模式。首先,从设备会验证功能码、数据地址和数据范围等输入。然后,执行所请求的操作并发送与代码相符的响应。如果此过程中的任何步骤失败,则会向请求程序返回异常。这些请求的数据传输就称为PDU。 Modbus PDUPDU由一个单字节的功能码组成,后跟多达252字节的功能特定数据。 图4.Modbus PDU 功能码是第一个需要验证的项。如果用于接收请求的设备未识别功能码,则会返回异常。如果功能码被接受,则从设备会根据功能定义开始分解数据。
由于数据包大小限制为253字节,因此设备可传输的数据量有限。最常见的功能码可以在从数据模型中传输240到250字节的实际数据,具体取决于代码。 从设备功能执行正如由数据模型所定义,不同的功能会访问不同的概念数据块。一种常见的做法是让代码访问静态内存位置,但其他行为仍然可用。例如,功能码1(读取线圈)和3(读取保持寄存器)可以访问内存中相同的物理位置。而功能码3(读取保持寄存器)和16(写入保持寄存器)可以访问内存中完全不同的位置。因此,建议在定义从数据模型时考虑每个功能码的执行情况。 无论执行的是何种实际行为,所有从设备都应遵循每个请求的简单状态图。图5是功能码1(读取线圈)的状态图范例。 每个从设备必须验证功能码、输入数量、起始地址、总范围以及实际进行读取行为的从属定义功能的执行。 尽管上面的状态图包含了静态地址范围,但真实系统的需求可能会导致静态地址范围与所定义编号有所不同。在某些情况下,从设备无法传输协议所定义的最大字节数。也就是说,如果主设备请求0x07D0输入,从设备只能用0x0400进行响应。同样,从数据模型能够将可接受线圈值的范围定义为地址0到500。如果主设备从地址0开始请求125,则没有问题,但如果主设备从地址400开始发出相同的请求,最后一个线圈将位于地址525,这无疑超出了该设备的范围,因而会出现状态图所定义的异常02。 标准功能码规范中列出了每个标准功能码的定义。即使对于最常见的功能码,主设备上启用的功能与从设备可处理的功能之间也会出现不匹配的情况,这种情况无法避免。为了解决这个问题,Modbus TCP规范的早期版本定义了三个一致性类。官方的Modbus一致性测试规范虽未引用这些类,而是在每个功能的基础上定义一致性,但这些内容仍然便于理解。建议任何文档都遵循测试规范,并根据所支持的代码(而不是传统分类)来定义其一致性。 0类代码0类代码通常被认为是有效Modbus设备的最低配置,因为此类代码可使主设备能够读取或写入数据模型。 1类代码1类功能码由访问所有类型的数据模型所需的其他代码组成。在原始定义中,此列表包含功能码7(读取异常)。但是,当前规范规定此代码为仅限于串行的代码。 Modbus封装接口Modbus封装接口(MEI)代码(即功能43)用于封装Modbus数据包内的其他数据。目前,提供了两个MEI编号,即13 (CANopen)和14(设备识别)。 功能43/14(设备识别)非常有用,因为它允许传输多达256个唯一的对象。其中一些对象已预定义并预留,例如供应商名称和产品代码,但应用程序可以将其他对象定义为作为通用数据集传输。 此类代码并不常用。 异常从设备使用异常来指示各种不良状况,比如错误请求或不正确输入。但是,异常也可以作为对无效请求的应用程序级响应。从设备不会响应发出异常的请求,而是忽略不完整或损坏的请求,并开始等待新的消息传入。 异常以定义好的数据包格式报告给用户。首先,将功能码返回给等同于原始功能码的请求主设备,设置最高有效位的情况除外。这等同于为原始功能码的值加上0x80。异常响应包括一个异常码,用于代替与给定功能响应相关的正常数据。 根据标准,四个最常见的异常码是01、02、03和04。表7中显示了这些代码,并附有每个功能的标准含义。
|