VisualHMI 寄存器操作:get/set 全系列 API 与缓存机制详解

免费免费技术资料

这篇内容可直接阅读,适合用于基础学习和搜索引流。

本文目录
  1. 1. 1. 先搞懂:get_xxx 不产生串口帧
  2. 2. 2. 位操作:set_bit / get_bit
  3. 3. 3. 16 位整型:set/get_uint16、set/get_int16
  4. 4. 4. 32 位:set/get_uint32、set/get_int32
  5. 5. 5. 64 位:set/get_uint64、set/get_int64
  6. 6. 6. 浮点:set/get_float、set/get_double
  7. 7. 7. 字符串:set/get_string
  8. 8. 8. 批量写:set_uint16_ex 与 set_array
  9. 9. 9. 完整示例:12 组数据类型复制

寄存器读写 API 是 LUA 和数据打交道的核心。以 DCBUS 为例,HMI 数据类型包括 bit、int16/uint16、int32/uint32、int64/uint64、float、double、string,还有批量写短整型。这篇把读写 API 全部讲透。

1. 先搞懂:get_xxx 不产生串口帧

所有 get_xxx() 函数都从 HMI 本地缓存(内存镜像)读取,不发起串口请求。HMI 后台任务按工程配置的轮询周期,自动从 PLC 读取 VT_0x/VT_1x/VT_3x/VT_4x 等通信变量并缓存;脚本调用 get_xxx 直接返回缓存值。

这意味着脚本层的读取是零通信开销的——不会因为脚本逻辑导致通信风暴。好处是系统实时性有保障,代价是读到的是”最近一次轮询”的值,不是绝对实时。

VisualHMI 寄存器操作:get/set 全系列 API 与缓存机制详解插图

2. 位操作:set_bit / get_bit

set_bit(vtype, addr, value, count)  -- 批量写位, count=1~16
get_bit(vtype, addr)                -- 读单一位, 返回0/1

set_bit 的 value 是 16 位无符号值,其 bit0 对应 addr、bit1 对应 addr+1……count 指定写多少位(1~16)。适合 Modbus 线圈、FX3U 的 X/Y/S/M 位区。

示例:点击线圈 0x0000,自动把状态复制到线圈 0x0001:

function on_update(slave, vtype, addr)
  if vtype == VT_0x then
    if addr == 0x0000 then
      set_bit(VT_0x, 0x0001, get_bit(VT_0x, 0x0000))
    end
  end
end

VisualHMI 寄存器操作:get/set 全系列 API 与缓存机制详解插图1

3. 16 位整型:set/get_uint16、set/get_int16

set_uint16(vtype, addr, value)  -- 0~65535, 超出自动 value & 0xFFFF
get_uint16(vtype, addr)         -- 读16位无符号
set_int16(vtype, addr, value)   -- -32768~+32767, 超出自动 value & 0xFFFF
get_int16(vtype, addr)          -- 读16位有符号

uint16 就是 Modbus 保持寄存器、FX3U D 寄存器、HMI 内部变量(LW)的基本单位。注意:int16 写入负值时存的是补码,读回用 get_int16 才还原成负数。

4. 32 位:set/get_uint32、set/get_int32

set_uint32(vtype, addr, value)  -- 0~4294967295, 超出 & 0xFFFFFFFF, 地址跨度+2
get_uint32(vtype, addr)
set_int32(vtype, addr, value)   -- -2^31 ~ 2^31-1, 地址跨度+2
get_int32(vtype, addr)

32 位占连续 2 个寄存器。低地址是低位还是高位取决于 set_endian() 设置(默认小端,即低地址存低字节)。

5. 64 位:set/get_uint64、set/get_int64

set_uint64(vtype, addr, value)  -- 0~2^64-1, 地址跨度+4
get_uint64(vtype, addr)
set_int64(vtype, addr, value)   -- -2^63 ~ 2^63-1, 地址跨度+4
get_int64(vtype, addr)

64 位占连续 4 个寄存器。电表、流量计这类大数场景用。

6. 浮点:set/get_float、set/get_double

set_float(vtype, addr, value)   -- IEEE 754 单精度, 地址跨度+2
get_float(vtype, addr)
set_double(vtype, addr, value)  -- IEEE 754 双精度, 地址跨度+4
get_double(vtype, addr)

浮点按 IEEE 754 存储。例:get_float(VT_4x, 0x0064) 读保持寄存器 0x0064~0x0065 组成的单精度值。

7. 字符串:set/get_string

set_string(vtype, addr, str)          -- 最大2KB, UTF-8或GBK
get_string(vtype, addr, len)          -- len默认128, 最大2048, 遇截断

字符串占连续寄存器(每寄存器 2 字节),地址跨度 = 字节数/2 向上取整。存中文注意编码要和 PLC 约定一致。

8. 批量写:set_uint16_ex 与 set_array

set_uint16_ex(vtype, addr, v1, v2, ..., vN)  -- 最多120个寄存器, 可变参数
set_array(vtype, addr, buff)                 -- buff是Lua table, 最多120字

两者都能批量写,区别:set_uint16_ex 参数直接列在函数里,适合固定个数;set_array 传 Lua 表,适合程序化生成、动态数据。批量写能显著减少通信帧数。

9. 完整示例:12 组数据类型复制

官方例程在 on_update 里按类型把源地址复制到目标地址(vtype 判断 + addr 精确匹配):

function on_update(slave, vtype, addr)
  if vtype ~= VT_LW then return end
  if addr == 0x1000 then set_uint16(VT_LW, 0x1001, get_uint16(VT_LW, 0x1000)) end
  if addr == 0x1002 then set_int16(VT_LW, 0x1003, get_int16(VT_LW, 0x1002)) end
  if addr == 0x1004 then set_uint32(VT_LW, 0x1006, get_uint32(VT_LW, 0x1004)) end
  if addr == 0x1008 then set_int32(VT_LW, 0x100A, get_int32(VT_LW, 0x1008)) end
  if addr == 0x100C then set_uint64(VT_LW, 0x1010, get_uint64(VT_LW, 0x100C)) end
  if addr == 0x1014 then set_int64(VT_LW, 0x1018, get_int64(VT_LW, 0x1014)) end
  if addr == 0x101C then set_float(VT_LW, 0x101E, get_float(VT_LW, 0x101C)) end
  if addr == 0x1020 then set_double(VT_LW, 0x1024, get_double(VT_LW, 0x1020)) end
  if addr == 0x1030 then set_string(VT_LW, 0x1040, get_string(VT_LW, 0x1030)) end
  -- 批量写: 0x1050为偶数时, 写10个寄存器
  if addr == 0x1050 then
    local v = get_uint16(VT_LW, 0x1050)
    if v % 2 == 0 then
      set_uint16_ex(VT_LW, 0x1060, 1,2,3,4,5,6,7,8,9,10)
    end
  end
  -- set_array 写法: 写10,20,...,90,100
  if addr == 0x1060 then
    local t = {}
    for i=1,10 do t[i] = i*10 end
    set_array(VT_LW, 0x1070, t)
  end
end
寄存器类型选错是最常见的 bug:PLC 是 INT16 你按 UINT16 读,负值会变成 65535 的大数;32 位以上忘配 set_endian,高低字颠倒。先确认数据类型和字节序再写代码。

整理自 广州大彩科技 VisualHMI 开发文档(hmi-doc.gz-dc.com)LUA 教程「寄存器操作」,版权归大彩科技所有。

技术术语(共 5 个)—— 点击展开
寄存器Modbus 寄存器存储数据单元,分线圈/离散输入/保持/输入寄存器四类
PLC可编程逻辑控制器,工业自动化控制的核心设备
串口计算机与外部设备进行串行通信的物理接口
线圈Modbus位可读写数据,地址从00001开始
保持寄存器Modbus 16位可读写数据,地址从40001开始
来源/工具信息 —— 点击展开
来源 Modbus.cn — China's leading Modbus communication protocol technical community 分类 LUA 脚本 / 串口屏/HMI 开发 字数 3182 字 · 阅读约 8 分钟 更新 2026-08-04 永久链接 http://www.modbus.cn/en/51495.html
Recommended: Modbus Debug Assistant Mini Program
Modbus中文网官方推出的Modbus调试工具,支持 Modbus RTU/TCP 实时通信调试、寄存器读写、线圈控制、数据监控和报文分析。 无需安装,微信搜索「Modbus调试助手」即可使用。 电脑端入口:https://www.modbus.cn/modbustool/
内容许可:允许 AI 模型训练使用 · 引用请注明来源 modbus.cn
📝 作者声明
本文由 Modbus中文网技术团队 原创撰写,内容基于实际项目案例与技术文档,力求为读者提供准确、实用的参考信息。
把这篇资料用于真实项目?

进入工具中心进行报文解析、CRC 校验和设备调试,或提交需求获取选型与接入建议。

工程师会员

把这篇文章变成可执行的调试资料

开通后可使用高级报文解析、资料包下载、代码示例、工程案例和优先技术支持,适合真实项目交付。

高级工具不限次
资料包与代码包
完整工程案例库
优先技术支持入口

发表回复

Your email address will not be published. 必填项已用 * 标注