使用 SerialTool 的 Modbus RTU、ASCII 和 TCP

最后更新于 作者 Oliver Reed

什么是 Modbus

Modbus 协议是一种串行通信协议,由 Modicon® 于 1979 年创建(该公司现已成为 Schneider Electric 集团的一部分),用于实现其可编程逻辑控制器(PLC)之间的通信。它已成为工业通信领域的 de facto 标准,如今也是全球工业电子设备中使用最广泛的连接协议之一。Modbus 是一种免版税协议,其规范发布在 The Modbus Organization 网站上。

简单来说,它是一种通过串行线路在电子设备之间传输信息的方法。请求信息的设备称为 Modbus Client,提供信息的设备称为 Modbus Server。在标准 Modbus 网络中,有 1 个客户端和最多 247 个服务器,每个服务器都有从 1 到 247 的唯一地址。客户端也可以向服务器写入信息。


该协议最初用于工业领域,后来也逐步被应用到其他行业,并成为最普及的协议之一。即使在今天,虽然它已经有 40 多年历史,仍然被广泛用于操作面板、PLC、家庭自动化系统,甚至 Arduino 这样的简单设备中。

通过串口传输 Modbus RTU 和 ASCII

在协议诞生时,通信就是为串口而设计的,因此这一功能已在 SerialTool 中实现。 Modbus 常用于在 SCADA(Supervisory Control and Data Acquisition)系统中,将监控计算机与远程终端单元(RTU)连接起来。根据数据传输格式的不同,协议分为:

  • MODBUS RTU - 数据以十六进制格式传输。
  • MODBUS ASCII - 数据以 ASCII 格式传输。

两种情况下的错误校验方式不同:在 MODBUS RTU 中使用 CRC(Cyclic Redundancy Check,循环冗余校验),附加在命令后;而在 MODBUS ASCII 中使用 LRC(Longitudinal Redundancy Check,纵向冗余校验),同样附加在命令之后。

Modbus TCP 传输

1999 年,专用于采用 TCP/IP 协议族网络的“Modbus TCP”被开发出来:实际上,它是基于 TCP/IP 的串行 Modbus RTU 版本,因此可以在 Internet/Intranet 网络上通信。近年来,TCP/IP 版本的使用越来越广泛,因为它是 Open Source、实现简单、开发成本低,而且几乎不需要复杂的硬件支持。

两种情况下的错误校验方式不同:在 MODBUS RTU 中使用 CRC(Cyclic Redundancy Check,循环冗余校验),附加在命令后;而在 MODBUS ASCII 中使用 LRC(Longitudinal Redundancy Check,纵向冗余校验),同样附加在命令之后。

Modbus TCP/IP 协议使用二进制数据编码和 TCP/IP 的错误检测机制。与串行 Modbus 不同,TCP/IP 版本是面向连接的,并且允许同时连接到同一个 slave 或多个设备。Modbus TCP/IP 同样采用 master-slave 模式;此外,这种通信还使用四种消息类型。

Modbus 位于 ISO/OSI 协议栈的第 7 层(应用层),定义了称为 framing 的报文格式以及数据和控制功能的传输方式。通信遵循 client-server 模式。该协议定义了不依赖于底层通信层的 Protocol Data Unit(PDU)。Application Data Unit(ADU)则增加了用于寻址和错误控制的附加字段。

SerialTool Modbus Client(Master / Polling)

SerialTool 是一款支持 Modbus RTU、ASCII 和 TCP 的客户端工具,具备 polling、寄存器扫描、流量监控和实时图表功能,可用于工业设备的测试与调试。

Modbus Client 允许您通过串口(RTU 或 ASCII)或网络(基于 IPv4 或 IPv6 的 TCP)连接到 Modbus Slave/server 设备,使用标准 Modbus 功能读写数据,并创建具有自定义映射的 Modbus 设备以执行定时 polling。
在原型设备中,您可以添加 Modbus 结构(Discrete Output Coils、Discrete Input Contacts、Analog Input Register、Analog Output Holding Register),并保存设备以便日后重新加载。该 Modbus 原型设备还可以导出为 Text、CSV 或 PDF 格式,便于直观地共享。
当具有正确映射的设备创建完成后,即可通过定时 polling 直接读取 Slave 设备中的值,并以实时图表形式显示。
SerialTool 还提供查看 Modbus 流量(Serial 和 TCP)的功能,可在专用终端中查看已发送和已接收的数据。高级终端支持数据导出以及对进出数据的实时过滤。
SerialTool 还可通过 Modbus Scanner 功能扫描远程 Slave 设备。通过设置合适的过滤条件,即使不知道当前支持哪些寄存器,也可以尝试对远程设备(Modbus Slave)进行映射。对于需要探索特性未知或只部分了解的设备时,Modbus Scanner 功能尤其有用。

下面是 SerialTool Modbus 模块的主界面:

Modbus Client (Master/Polling) Main page

SerialTool Modbus Client 主界面

主界面突出了 SerialTool 和 Modbus Client(Master)的主要功能。

SerialTool Modbus Client(Master / Polling)

在界面左侧,您可以选择串口连接或 TCP 连接模式:

Modbus Client Connection

Modbus Client 连接界面

如上所述,串行 Modbus 协议分为 RTU 和 ASCII 两种类型。为了正确地与远程设备通信,在串口连接情况下,必须知道您的 Slave 设备支持哪一种 Modbus 协议类型。

而 ModBus TCP 连接支持 IPv4 和 IPv6。要通过 TCP 设置 Modbus 连接,需要配置 slave 的 IP 地址以及远程端口。

在连接界面中,有两个与 Modbus Slave 设备响应时间相关的参数。
一个是通用响应超时(Response Timeout),超过该时间 Client(Master)将停止等待 slave 响应;另一个是从接收到 Slave 最后一个字节开始计算的超时。

Modbus ENRON/Daniel 仿真

连接参数中提供了 ENRON/Daniel 仿真(通常也称为 Enron Modbus 或 Daniels Modbus),它指的是标准 Modbus 通信协议的一种特定变体。
它最初由 Enron Corporation 开发,并广泛应用于 Daniel Measurement and Control 的流量计算机中。随着时间推移,它成为电子流体测量(EFM)领域,尤其是 Oil & Gas 行业中的事实标准。

在设备上启用 ENRON/Daniel 仿真后,Modbus 的行为会发生变化,以支持以下关键特性:

  • 1. 单个寄存器中的 32 位数据处理: 这是最重要的技术差异。在 Standard Modbus 中,寄存器为 16 位(2 字节),读取 32 位值需要读取两个寄存器;而在 Enron Modbus 中,32 位值被映射到单个寄存器中(每个寄存器 4 字节)。
  • 2. 特定的地址映射: 它为 32 位数据使用预定义的地址范围。5000 系列(例如 45001 - 45999)用于 Long Integers,而 7000 系列(例如 47001 - 47999)用于 Floating Points。
  • 3. 历史数据和事件: 它支持提取历史日志和报警归档的专用命令,而标准 Modbus 几乎仅用于实时读取。
  • 4. 无 Offset: 请求地址与寄存器编号完全一致,消除了标准 Modbus 中常见的“+1 offset”问题。

总结: 当与 Oil & Gas 行业内传输原生 32 位数据的设备通信时,这种仿真对于避免通信错误(字节错位)至关重要。


Modbus Client 功能

在界面中央区域可以看到 SerialTool 支持的 Modbus 功能。

Modbus Client 功能

Modbus Client 模式支持的功能

ModBus 客户端的功能可总结如下表。

功能码 操作 表名 / 描述
0x01 读取 Discrete Output Coils
0x02 读取 Discrete Input Contacts
0x03 读取 Analog Output Holding Register
0x04 读取 Analog Input Registers
0x05 单写 Discrete Output Coil
0x06 单写 Analog Output Holding Register
0x07 读取 Exception Status
0x08 诊断 诊断 (Serial Line only)
0x0B (dec 11) 读取 Comm Event Counter (Serial Line only)
0x0F (dec 15) 多写 Discrete Output Coils
0x10 (dec 16) 多写 Analog Output Holding Registers
0x11 (dec 17) 报告 Server ID (Serial Line only)
0x16 (dec 22) 掩码写入 Holding Register
0x17 (dec 23) 多重读写 Holding Registers
0x2B / 0x0E (dec 43 / 14) 读取 Device Identification

Modbus 数据结构

信息存储在 Server 设备中的四个不同表中。两个表用于存储离散的开/关值(coils),另外两个表用于存储数值(registers)。Coils 和 registers 各自都有只读表和读写表。每个表包含 9999 个值。每个 coil 或 contact 为 1 bit,数据地址范围为 0000 到 270E。每个 register 为 1 word = 16 bits = 2 bytes,数据地址范围同样为 0000 到 270E。

Coil/Register 编号 数据地址 类型 表名
1-9999 0x0000 to 0x270E 读/写 Discrete Output Coils
10001-19999 0x0000 to 0x270E 只读 Discrete Input Contacts
30001-39999 0x0000 to 0x270E 只读 Analog Input Register
40001-49999 0x0000 to 0x270E 读/写 Analog Output Holding Register

Modbus 设备

SerialTool 允许创建一个 Modbus Slave 设备,用于表示您打算连接的 Slave 设备的寄存器映射。 该映射非常重要,因为它可以在本地表中显示远程 slave 设备中的数值。

Modbus Client 功能

Modbus Slave functions map

Modbus Client 可用功能

通过功能栏,您可以使用“Load Device”加载此前创建的设备,使用“Save Device”保存当前设备,并通过“Add Item”添加单个寄存器或通过“Add Items”添加多个寄存器到设备映射中。

Add Multiple Modbus Registers

向 Modbus 设备映射中添加 Modbus 寄存器


Modbus 设备 Slave Memory Mapping

Modbus Slave 设备内存区域(Modbus 设备)

创建好 Modbus Slave 设备映射后,SerialTool 允许将其保存以供后续使用,或将内容导出为 CSV、Text 或 PDF 格式,以便与第三方共享和处理。 下图展示了 Modbus Slave 设备映射导出的一个示例:

Modbus Slave Mapping

Modbus Slave 设备映射 PDF 导出示例

您可以通过此链接下载 PDF。

Modbus Polling

创建 Modbus Slave 设备后,就可以执行 polling,也就是对所连接 slave 设备中的某些寄存器进行定时读取。
为此,首先需要创建并映射 Slave,然后添加您希望执行 polling 的寄存器,如下图所示:

Modbus Master to Slave Polling

该图显示了如何向指向 slave 的 polling 中添加一个项目

向 polling 添加一个或多个项目后,就可以开始对与 polling 列表关联的项目执行 polling。

Modbus Master to Slave Polling Mask

该图显示了为 polling 选择的项目

访问 Modbus 功能

SerialTool 的 Modbus 客户端(Master/Polling)设计为可通过三种模式执行功能:

Modbus execute function

Modbus 功能执行

  • "Execute from Device Table" - 根据设备映射执行 Modbus 功能。
  • "Execute Function" - 直接执行 Modbus 功能,并在日志窗口中显示结果。
  • "Send Raw Data" - 发送由十六进制字节组成的直接请求,并等待响应。

Execute from Device Table

该模式直接使用本地加载或创建的设备表来执行所选的 Modbus 功能。 用户可以选择 Modbus 引用类型,例如 Coils、Discrete Inputs、Holding Registers 或 Input Registers,设置起始地址和需要读取或写入的元素数量,然后一键将命令发送给 slave。
这种模式的主要优势在于,结果会立即反映到设备映射中,并更新本地表中显示的值。 因此可以获得对远程设备状态的有序且持久的表示,这在测试以及监控和维护活动中都非常有用。
当命令涉及写功能时,SerialTool 可通过选择数据类型、显示格式以及要写入所选寄存器的内容,轻松准备待发送数据。 因此,当您希望直接针对 Modbus 设备的逻辑结构工作时,这种模式特别合适。

Execute Function

Execute Function 模式允许用户直接从可用功能码列表中选择一个 Modbus 功能来执行, 例如读取 coils、读取 discrete inputs、读取 holding registers、读取 input registers、单个或多个写入以及协议支持的其他功能。
在这种情况下,操作不仅限于在设备映射中显示,因为结果会被输出到应用程序的日志区域。 当您希望快速验证收到的响应内容、测试某个特定的 Modbus 功能,或者在不必修改设备映射的情况下对不同地址和数量进行针对性测试时,这种方式尤其有用。
Execute Function 模式也非常适合调试,因为它可以让您立即看到执行结果、slave 返回的错误以及与请求和响应相关的信息。

Send Raw Data

该功能以十六进制格式向 slave 发送和接收任意命令。 用户可以手动输入要通过当前连接(例如串口或 TCP/IP)发送的字节序列,软件不会自动构建帧。
该功能对于高级测试、逆向工程、诊断或 Modbus 设备及兼容协议的验证非常有用。 实际上,客户端会精确发送用户输入的字节,从而完全控制数据包内容。这样就可以模拟自定义请求、测试异常响应或发送手动准备好的完整帧。
启用等待响应选项后,SerialTool 还可以接收 slave 返回的帧并在流量日志中显示,从而能够立即比较发送和接收的数据。

Modbus Raw Data

发送 Raw 数据

Modbus Scanner 功能

SerialTool 包含对已连接 Slave 设备的 Modbus 地址进行扫描的功能。 该功能可快速探索从起始地址到结束地址的地址范围,并且可以指定扫描时要使用的功能码。
当远程设备的完整映射并不清楚,或者希望确认哪些地址有效、哪些地址包含有意义的数据时,扫描器尤其有用。 对于每个被查询的地址,SerialTool 都会在表中显示所用功能类型、地址、读取到的值以及操作结果。
这种模式可以显著加快与第三方设备的诊断和集成工作,因为它能够快速识别 slave 实际使用的 Modbus 内存区域,并导出扫描结果用于后续分析或共享。

Modbus Slave Scanner

地址表

Slave Modbus 寄存器图表

Modbus 寄存器的值可以显示在图表中。 该功能允许将设备映射中的一个或多个元素链接到专用图表窗口,在 polling 或更新操作期间随时间绘制其值。
每个连接到图表的寄存器都可以用单独的曲线显示,并通过特定颜色以及诸如 Modbus 引用、地址、当前值和元素名称等信息进行标识。 这样就可以轻松观察模拟量、设定值、测量值或在设备运行期间变化的数值寄存器的时间趋势。
图表功能对于监控、测试和动态分析尤为有用,因为它可以让您立即看到数据如何随时间变化,而不只是停留在表格读取层面。

Modbus Client/Slave Chart

Modbus 寄存器图表

Modbus 流量日志

所有发送和接收的命令都会以字节形式显示在 Modbus 流量日志窗口中。 流量日志是通信调试的基础工具,因为它可以详细展示客户端发送的数据以及从 slave 设备接收的数据,并以可读形式显示字节序列。
借助该窗口,可以检查帧的实际内容、验证生成的命令是否正确,并诊断超时问题、异常响应、Modbus 异常或意外数据。 无论是在正常使用客户端、自动 polling 还是发送 raw 数据时,都可以查看这些流量。
流量窗口还提供高级功能,例如以 ASCII 或十六进制格式复制数据、保存到文件、在内容中搜索、选择行以及颜色、字体、间距和显示设置等图形自定义选项。 这使得流量日志不仅仅是一个查看器,也是开发人员、技术人员和系统集成人员非常有价值的操作工具。

Modbus Client/Slave Traffic

Modbus 流量