3. 数据模型核心概念

Modbus 之所以能在几十年里保持生命力,很大程度上得益于它极其简洁的数据模型。协议并不规定设备内部如何存储数据,而是把可访问的数据抽象成四张“表”,每张表有固定的地址空间、访问权限和典型用途。理解这四种基本数据类型,是后续寄存器规划、地址映射和通信调试的基础。

核心记忆口诀:线圈可读可写、离散输入只读、保持寄存器可读可写、输入寄存器只读。前两者是 1 位布尔量,后两者是 16 位字量。

一、四种数据类型的定义与访问权限

Modbus 数据模型按“位/字”和“只读/读写”两个维度交叉划分,形成四种类型。它们各自拥有独立的地址空间,地址编号从 1 开始,但协议报文中的实际偏移量从 0 开始,这是初学者最容易混淆的地方。

数据类型数据宽度访问权限典型用途常用功能码
线圈(Coil)1 位可读可写继电器输出、指示灯、启停命令01 / 05 / 15
离散输入(Discrete Input)1 位只读限位开关、按钮、故障触点02
保持寄存器(Holding Register)16 位可读可写设定值、PID 参数、配方数据03 / 06 / 16
输入寄存器(Input Register)16 位只读温度、压力、流量等测量值04

二、四类数据的信号链与访问关系

从现场信号到主站读写,四种数据类型构成两条清晰的信号链:一条是“采集链”,现场物理量经传感器进入从站,映射为离散输入或输入寄存器,主站只能读取;另一条是“控制链”,主站写入线圈或保持寄存器,从站据此驱动执行器或改变运行参数。下图展示了这一关系。

Modbus 四种数据类型的访问关系 主站 / 上位机 读写请求发起方 从站 / 现场设备 数据表持有方 现场物理世界 传感器 / 执行器 线圈 Coil 1 位 · 可读可写 功能码 01/05/15 离散输入 Discrete Input 1 位 · 只读 功能码 02 保持寄存器 Holding Register 16 位 · 可读可写 功能码 03/06/16 输入寄存器 Input Register 16 位 · 只读 功能码 04 请求 响应 采集 / 驱动 地址空间相互独立:线圈 00001~、离散输入 10001~、输入寄存器 30001~、保持寄存器 40001~ 同一编号在不同类型中含义不同,规划时必须明确“类型 + 地址”

三、方法流程:如何为四类数据分配地址

实际项目中,寄存器规划通常遵循以下流程,避免后期地址冲突和语义混乱。

  1. 梳理信号清单:列出所有需要通信的点位,标注是布尔量还是模拟量、是只读还是需要写入。
  2. 按类型归类:布尔量只读归入离散输入,布尔量可写归入线圈;模拟量只读归入输入寄存器,模拟量可写归入保持寄存器。
  3. 分配连续地址:同一类型内按功能分区连续编号,预留 10%~20% 余量,便于后期扩展。
  4. 建立映射表:记录“设备点位—Modbus 类型—协议地址—PLC 变量”的对应关系,作为调试和交接文档。
  5. 验证访问权限:确认只读数据不会被主站写入,可写数据不会被从站错误覆盖。
# 寄存器规划映射表示例
点位名称        类型            协议地址    数据格式    说明
启动命令        线圈            00001       BOOL        1=启动
停止命令        线圈            00002       BOOL        1=停止
运行状态        离散输入        10001       BOOL        只读反馈
故障报警        离散输入        10002       BOOL        只读反馈
目标温度        保持寄存器      40001       INT16       单位 0.1℃
实际温度        输入寄存器      30001       INT16       单位 0.1℃
实际压力        输入寄存器      30002       UINT16      单位 0.01MPa

四、案例场景:一个温控设备的点位规划

假设一台温控设备需要与上位机通信,现场有一个启动按钮、一个停止按钮、一个运行指示灯、一个故障触点、一路温度传感器和一路压力传感器,同时上位机需要下发目标温度。按四类数据划分:启动/停止命令写入线圈;运行指示灯和故障触点作为离散输入反馈;目标温度写入保持寄存器;实际温度和实际压力作为输入寄存器上报。这样划分后,主站读输入寄存器即可获得测量值,写保持寄存器即可修改设定值,权限边界清晰,不会出现“读到了命令区”或“误写了测量值”的问题。

调试技巧:用 Modbus Poll 或类似工具时,先确认功能码与数据类型匹配。读输入寄存器必须用功能码 04,用 03 去读输入寄存器会返回异常码 02(非法数据地址),这是现场最常见的误判之一。

五、常见误区与复盘

  • 误区一:把四类数据当成同一块内存。它们地址空间独立,00001 和 10001 是两个完全不同的点位,不能混用。
  • 误区二:忽略 1 基地址与 0 基偏移的差异。文档写 40001,报文里偏移是 0;文档写 40010,报文偏移是 9。规划时统一口径,避免差一错误。
  • 误区三:只读数据被写入。输入寄存器和离散输入在协议层面只读,若主站强行写,从站应返回异常响应,而不是静默接受。
  • 误区四:地址不连续导致读取效率低。把同一功能的点位集中排列,可以用一次请求读取多个寄存器,减少报文数量。
复盘要点:寄存器规划不是“把点位塞进去”就结束,而是要在类型、权限、地址、数据格式四个维度上保持一致。建议在项目初期就输出映射表,并在联调前用脚本或工具做一次地址冲突检查。

掌握这四种基本数据类型,就掌握了 Modbus 数据模型的骨架。后续无论是功能码选择、报文解析,还是寄存器地址规划,都可以回到这张“四象限”图上进行判断:先问是位还是字,再问是只读还是可写,答案自然清晰。