Modbus 服务端
将转发组内的变量映射为 Modbus TCP 或 Modbus RTU 的线圈、离散输入、输入寄存器或保持寄存器,供外部 Modbus 主站读取,并按权限接受写入。
转发组范围和目标启停见数据转发。本页只说明 Modbus 类型、站号、数据格式、地址映射、客户端权限和专用调试。
功能入口
进入“开发配置 → 数据转发”,按以下顺序配置:
- 保存转发组变量范围;只有范围内变量才可以映射到 Modbus 地址。
- 新增目标,选择“Modbus 服务端”,填写目标名称、启用状态、日志级别和启动超时。
- 打开“目标属性”,先选择 Modbus 报文类型和通道类型,再配置协议、权限、串口或 TLS 参数。
- 保存目标后,打开“变量属性”,为每个对外提供的变量填写必填的“从站变量地址”。
- 启用目标,用外部 Modbus 主站或目标“调试”页读取测试点;需要写入时先确认三层权限。
协议与通道
| 参数 | 默认值 | 如何配置 |
|---|---|---|
| Modbus类型 | ModbusTcp | 当前版本只有 ModbusTcp(MBAP 报文)和 ModbusRtu(二进制 RTU + CRC16),没有 ASCII 选项。TCP 通常配 TcpService;RTU 通常配 SerialPort。 |
| 默认站号 | 1 | 变量地址没有 S= 前缀时使用。站号必须与主站点表一致;使用多站点时在地址中显式写站号。 |
| 多站点模式 | 开启 | 开启后同一目标可映射多个站号;只使用一个站号时可关闭。 |
| 通道类型 | TcpService | 当前可选 TCP 客户端、TCP 服务端、串口和 UDP。通道类型决定地址、串口、DTU 和 TLS 字段;通用枚举中的 Other 不在当前表单选择范围内。 |
选择通道后,只填写该通道对应的字段。TCP 服务端通常在“本地绑定地址”填写 0.0.0.0:502;生产环境建议绑定指定网卡地址,或使用客户端权限列表限制来源。串口通道填写串口参数;主动 TCP 连接需要模拟 DTU 注册时,再填写 DtuId 和 DtuId是否Hex。TCP 服务端或 UDP 需要 DDP 封装时选择对应“Dtu服务类型”。TLS 仅用于 TCP 客户端和 TCP 服务端;UDP、串口不使用这组 SSL 配置。
TCP 连接方向与 Modbus 角色分开配置。选择 TCP 客户端时,由网关主动连接远端监听主站,网关仍是响应寄存器请求的从站。RTU 可运行在串口或 TCP 链路上,RTU over TCP 仍使用 CRC 帧,普通 MBAP 主站不能直接互通。UDP 也应选择双方一致的报文格式。
数据格式与权限
| 参数 | 默认值 | 如何配置 |
|---|---|---|
| 数据解析顺序 | ABCD | 可选 ABCD、BADC、CDAB、DCBA,必须与主站的字节序和字序一致。 |
| 字符串反转字节 | 关闭 | 按字反转字符串字节;只在主站字符串布局相反时开启。 |
| 允许RPC写入 | 开启 | 目标级写入总开关。只读监控服务应关闭。 |
| 客户端权限列表 | 空 | 仅 TCP 服务端的入站连接使用。空列表不限制来源 IP;非空时只允许匹配 AllowedClientIp 的客户端,写入还须 AllowWrite=true。串口、UDP 和主动 TCP 不使用这份入站 IP 列表。 |
| 立即写入内存 | 开启 | 控制成功协议写入是否立即保留到本服务的 Modbus 内存,不是现场 RPC 总开关。关闭时已映射点仍可执行现场写入,并随采集反馈更新服务值。 |
| 发送延时时间 | 0 毫秒 | 回复报文前等待的毫秒数。仅在主站明确要求报文间隔时调整。 |
通道、串口和容量属性
| 参数 | 默认值 | 如何配置 |
|---|---|---|
| 远程地址 | 127.0.0.1:502 | 仅客户端或需要远程端点的通道使用。Modbus TCP 服务端通常不填写。 |
| 本地绑定地址 | 0.0.0.0:502 | TCP 服务端监听地址。生产环境不要无条件监听全部网卡。 |
| 连接超时 | 3000 毫秒 | 建立连接的超时时间,最小 100 毫秒。 |
| 最大并发数 | 1 | 通用通道参数。当前被动服务初始化使用单请求限制,不能把较大表单值直接理解为等量并行请求保证。 |
| 最大连接数 | 10000 | 服务端允许的客户端连接上限,按现场客户端数量设置。 |
| 组包缓存时间 | 500 毫秒 | 粘包/拆包等待窗口,最小 100 毫秒。 |
| 客户端清理时间 | 120000 毫秒 | 空闲客户端清理,0 关闭任务;非零值至少 10000。实际关闭时刻受检查调度影响,不是固定请求延时。 |
| 心跳内容 / 心跳是否Hex / 心跳时间 | 空 / 关闭 / 60000 毫秒 | 主动 TCP 模式且已填写非空 DtuId 时,按需配置应用层心跳;Hex 开启后按十六进制解析内容。不能据此认定 TCP 服务端会周期发送。 |
| 串口 / 波特率 / 数据位 / 校验位 / 停止位 | COM1 / 9600 / 8 / None / One | 仅串口通道生效,必须与外部设备完全一致。 |
| DtrEnable / RtsEnable / 异步流 / 握手方式 | 开启 / 开启 / 开启 / 默认 | 按串口硬件流控和驱动要求配置。 |
| 串口输入/输出缓冲区大小 | 4096 / 2048 字节 | 长帧或持续流量不足时再增大。 |
| DtuId / DtuId是否Hex | 空 / 关闭 | 主动 TCP 模式连接后发送的注册标识及其文本/Hex 编码方式;与采集设备匹配传入 DTU 的 ID 配置用途不同。 |
| Dtu服务类型 | Default | TCP 服务端或 UDP 需要 DDP 帧时选择 DDP;普通 Modbus 链路保持 Default。 |
启用 SSL 时还需填写“SSL客户端证书”“SSL服务端证书”“SSL CA证书”“SSL目标主机名”“SSL协议”“允许不受信任证书”和“检查证书吊销”。服务端模式至少需要服务端证书;生产环境关闭“允许不受信任证书”。
组包缓存时间用于等待不完整帧,与连接超时、发送延时和历史缓存不同。例如同一请求两段间隔 350 毫秒,100 毫秒组包窗口可能丢失半帧,1000 毫秒窗口则可容纳这次分段。发送延时会增加请求往返时间,外部主站的响应等待预算也应覆盖它。
DTU、串口和 TLS
主动 TCP 连接可先发送文本或 Hex 的 DTU 注册标识,再发送周期心跳;心跳周期 0 关闭周期发送,注册仍可保留。这些字节不属于 Modbus 帧,远端需先分离注册和心跳。选择 DDP 时,终端还需完成 DDP 注册并封装业务帧,普通 MBAP 客户端不能直接使用该入口。配置字段见通道与传输。
串口 RTU 通常使用八数据位,两端的波特率、校验位、停止位和流控一致。无停止位会被系统串口拒绝;五数据位加一点五停止位即使被某些虚拟串口接受,也不能作为完整八位 RTU 物理链路的依据。硬件握手控制 RTS 时,不应再把手工 RTS 开关理解为独立控制。
TLS 服务端使用服务证书和私钥。当前 TCP 服务端关闭“允许不受信任证书”后,会要求并验证外部主站的客户端证书;应配置相应 CA 信任,并让主站携带有效证书和私钥,否则无法完成双向握手。服务端允许不受信任时,主站仍需独立验证网关服务证书。主动 TCP 模式中,“SSL目标主机名”用于核对远端证书 SAN,“SSL客户端证书”提供网关身份,CA 不能代替私钥。连接超时还包含握手等待,TCP 已接受不等于 TLS 已完成。开启吊销检查需要可用的 CRL 等来源;协议版本使用双方及系统实际支持的组合。
目标变量属性
保存目标后,打开“变量属性”,为每个需要提供给主站的变量配置 Modbus 映射。
| 参数 | 默认值 | 如何配置 |
|---|---|---|
| 从站变量地址 | 空(必填) | 填写对外暴露的 Modbus 地址。未填写或格式无效时,该变量不会建立映射。 |
| 数据类型 | Int16 | 选择 Object、String、Boolean、Byte、Int16、UInt16、Int32、UInt32、Int64、UInt64、Float、Double 或 Decimal;占用寄存器数量必须与主站点表一致。 |
| 允许RPC写入 | 开启 | 变量级写入权限。外部写入须通过目标与变量开关及源变量写权限;TCP 服务端配置了客户端权限列表时,还须命中允许写入的条目。 |
变量必须已在转发组范围内;新增目标变量属性不会把变量加入转发组。
地址规则
| 地址写法 | 数据区 | 常用读取功能码 |
|---|---|---|
00001 | 线圈 | FC1 |
10001 | 离散输入 | FC2 |
30001 | 输入寄存器 | FC4 |
40001 | 保持寄存器 | FC3 |
标准地址按 1 起始填写;当前 Modbus 地址解析只支持 TCP/RTU 对应的数据区:
S=2;40001:站号 2 的保持寄存器 40001。F=3;0:显式使用 FC3 和 0 起始偏移。40001.3:保持寄存器 40001 的第 3 位。
同一目标内的站号、功能码和起始地址组合不得冲突。多寄存器数据占用的地址不能与相邻变量重叠。
连续写入与完整覆盖
外部主站一次写入连续地址时,网关检查所有与写入范围相交的变量。每个相交变量都必须完整包含在本次写入内,并通过目标、客户端、映射变量和源变量的写入权限检查,才进入实际写入。
例如 Float 映射在 40001,占用两个寄存器:只写 40001 或只写 40002 属于部分覆盖,应被拒绝;写入两个寄存器才是完整值。如果一次写入跨过多个映射变量,应同时覆盖它们的完整范围,字符串、数组和多寄存器整数也按实际占用长度检查。
验证时先使用完整范围写入并回读,再测试部分覆盖及其中一个变量禁止写入的情况,确认无效请求不会触发该批变量的现场写入。范围和权限检查通过后,仍需逐项核对实际设备的写入结果;多个设备的执行不能视为一个原子事务。
从一个点完成读写闭环
- 将一个正常的 Int16 采集变量加入转发组,服务映射填写
40001,默认站号1,数据顺序ABCD。 - 独立主站连接监听端口,以 unit ID
1、FC3、偏移0、数量1读取,并与采集值和现场值比较。 - 把服务地址改为
40011后,外部改读偏移10;现场采集地址保持不变。映射为30001时使用 FC4,不能继续按 FC3 读取。 - 需要写入时恢复保持寄存器区,确认目标、客户端、目标变量及源变量权限,用外部主站写测试值,等待现场回读、采集值和外部再次读取一致。
- 分别关闭目标或单变量写许可,核对读取继续成功、写入被拒绝且现场值保持原值,再恢复配置。
未写 S= 时使用默认站号;显式 S=3;F=3;0 覆盖默认值。多站模式为各站提供独立空间,未映射站读到零不能视为读到现场数据。单站模式按默认站号响应,客户端应同时匹配报文格式、站号、功能码和偏移。
类型占用与字节顺序
| 类型 | 外部读取范围与解释 |
|---|---|
| Boolean | 线圈 00001 使用 FC1,离散输入 10001 使用 FC2,两者是独立空间。 |
| Byte | 一个字节;主站仍按两字节读寄存器,另一个字节可能保留相邻内存,不能把整字直接当 Byte。 |
| Int16、UInt16 | 一个寄存器,有符号与无符号值域不同。 |
| Int32、UInt32、Float | 两个寄存器;Float 使用 IEEE 754,不能按整数解释。 |
| Int64、UInt64、Double | 四个寄存器,整数与浮点编码不同。 |
| Decimal | .NET 十六字节布局,八个寄存器,不是通用 PLC 十进制格式。 |
| String | 地址中明确字节长度,例如 len=4;40001 占两个寄存器;UTF-8 编码,空间不足会截断,需要预留补零空间。 |
| Object | 当前没有任意对象到 Modbus 内存的通用映射,应选择明确类型。 |
Int32 数值 2345 在 ABCD 下为 00 00 09 29;BADC 为 00 00 29 09,CDAB 为 09 29 00 00,DCBA 为 29 09 00 00。双方按同一顺序还原,现场值不因目标顺序改变。字符串反转则是每个十六位字内交换字节,不是倒序整个文本。
目标调试
进入“开发配置 → 数据转发”,选择 Modbus 服务端目标后打开“调试”。
| 功能 | 作用 |
|---|---|
| 读写 | 按当前映射地址读取或写入,检查站号、功能码、数据类型和权限。 |
| 转发管线 | 查看转发组变量如何进入 Modbus 服务端映射。 |
| 协议服务 | 查看监听端点、已连接客户端和协议服务状态。 |
读写

转发管线

协议服务

先执行读取确认地址和格式。写入或断开客户端前,必须确认变量、客户端和现场影响。
读写调试直接访问当前服务内存,不会新建网络主站,也不能单独验证网络权限。对未映射地址 40101 写入并读回,只能证明偏移 100 的本地内存改变;它不会新增采集变量,也不证明现场发生写入。数组长度读取连续空间,批量模式则逐地址返回状态,未映射位置的零值不能当作第二个现场点。
验证方法
- 启用目标,确认协议服务正在监听。
- 使用外部 Modbus 主站连接服务端。
- 在每个已配置数据区读取一个测试变量,核对地址、值和数据格式。
- 需要写入时,确认目标、客户端和变量权限,再写一个安全值并核对网关变量。
常见问题
| 现象 | 检查方法 |
|---|---|
| 主站无法连接 | 通道类型、本地绑定地址、端口占用、防火墙、最大连接数和客户端权限。 |
| 主站读不到值 | 站号、功能码、目标变量地址、转发组范围和数据类型。 |
| 数值字节顺序不对 | 数据解析顺序、字符串反转、目标数据类型和主站格式。 |
| 写入被拒绝 | 目标“允许RPC写入”、客户端权限、变量权限和主站写功能码。 |
| 串口没有响应 | 串口占用、波特率、数据位、校验位、停止位、流控和帧间隔。 |