适用版本:1.0.27 更新日期:2026-10-09
Lua 脚本通过本节接口读写工程变量。寄存器类型 vtype 表示变量存储区,数据类型则由函数名决定;两者不能混用。整数地址可以写为十进制,也可以使用 0x 开头的十六进制。
完整的四区字/位、功能码、批量读写、轮询及双从站示例见 Modbus 脚本读写示例。
| 变量类型 | vtype | 地址说明 |
|---|---|---|
| LW 本地变量 | 1 | 字地址 0x0000~0xFFFF |
| RW 掉电保存变量 | 2 | 字地址 0x0000~0x7FFF |
| Modbus 0x 线圈 | 3 | 每地址一个位,使用工程配置的数值地址 |
| Modbus 1x 离散输入 | 4 | 每地址一个位;主站访问外部设备时只读 |
| Modbus 3x 输入寄存器 | 5 | 每地址一个 16 位字;主站访问外部设备时只读 |
| Modbus 4x 保持寄存器 | 6 | 每地址一个 16 位字,使用工程配置的数值地址 |
屏作为 Modbus Slave 时,屏内 Lua 可以更新 1x/3x 输入数据,供外部主站读取;外部主站仍不能经写功能码写入这两个区。
Modbus 使用数值地址,例如保持寄存器地址 100 写作 get_uint16(6, 100),不能仅凭设备标签 40101 就把 40101 直接代入。FX、DVP、信捷等 PLC 的 vtype 和地址范围按各自协议的软元件映射选择,不能套用 Modbus 类型表。
运行库没有预设 LW、RW、HOLDING 等 Lua 常量;需要时在自己的脚本中定义:
local LW = 1
local RW = 2
local HOLDING = 6
数值和位读取函数成功时返回一个数值,字符串读取返回字符串。set_* 成功时没有返回值;数值读写、位读写及写入接口在参数错误、地址或类型不支持、读写失败时抛 Lua 错误,可以用 pcall 捕获。字符串读取的部分读取规则见第 4 节。不能通过 set_uint16(...) == 0 判断成功。
主站 get_* 读取运行库中的缓存,调用后不会同步等待 PLC 应答。主站 set_* 校验通过后先提交本地可读值,再尝试发送 PLC 命令;函数正常返回或触发 on_update,均不等于 PLC 已执行。首次缓存值也不能作为设备在线的判断依据。
当前工程 Lua 使用 32 位有符号整数和 32 位浮点数。函数名中的 32/64 位描述寄存器的存储格式,不会扩大 Lua 的数值范围;64 位寄存器接口也不能直接接收任意 64 位整数。
这些函数的完整签名为 get_类型(vtype, addr) 和 set_类型(vtype, addr, value)。没有可选的位序、从站、字节序或通知参数;选择从站使用 select_slave,通知参数仅属于后面的 set_bit。
| 读函数 | 写函数 | 数据范围或表示 | 本地变量占用 |
|---|---|---|---|
get_uint16(vtype, addr) |
set_uint16(vtype, addr, value) |
整数 0~65535 | 1 字 |
get_int16(vtype, addr) |
set_int16(vtype, addr, value) |
整数 -32768~32767 | 1 字 |
get_uint32(vtype, addr) |
set_uint32(vtype, addr, value) |
可直接传入和正常返回的非负整数 0~2147483647 | 2 字 |
get_int32(vtype, addr) |
set_int32(vtype, addr, value) |
整数 -2147483648~2147483647 | 2 字 |
get_uint64(vtype, addr) |
set_uint64(vtype, addr, value) |
可直接传入和正常返回的非负整数 0~2147483647 | 4 字 |
get_int64(vtype, addr) |
set_int64(vtype, addr, value) |
可直接传入和正常返回的整数 -2147483648~2147483647 | 4 字 |
get_float(vtype, addr) |
set_float(vtype, addr, value) |
32 位浮点数,约 7 位有效十进制数字 | 2 字 |
get_double(vtype, addr) |
set_double(vtype, addr, value) |
寄存器为 64 位浮点格式,但 Lua 输入和输出仍只有 32 位浮点精度 | 4 字 |
vtype 和 addr 必须为整数;整数写函数的 value 也必须为整数。浮点写函数接收数值。地址跨度不得回绕,例如从 0xFFFF 起只能读写 1 个本地字,不能存储 32 位或 64 位值。不同 PLC 的原生元素宽度、读写权限和数据类型支持仍以该协议为准。
本地 LW/RW 的多字数值按高字在前保存;PLC 的数值字节序使用工程中对应协议的设置。完整的 UINT32/UINT64/INT64 存储范围超过当前 Lua 整数范围:读取超出上表范围的值时,可能出现高位截断或符号变化;get_uint64 仅在原始值超过 0x7FFFFFFFFFFFFFFF 时另行报错,不能用它自动检测所有 Lua 范围溢出。
需要保留完整的较大整数时,可在 LW/RW 或普通 16 位字寄存器中按字读取,再分别处理各字;不要把超范围的整数文本转成 Lua 数值后写入。PLC 原生 32 位软元件应按该协议的元素规则处理,不能直接套用连续 LW 字的拆分例子。没有注册 get_uint8、set_uint8、get_int8 或 set_int8 接口。
下面在相互独立的地址保存不同类型,再读取:
local LW = 1
function on_init()
set_uint16(LW, 0x1014, 9)
set_int16(LW, 0x1020, -9)
set_uint32(LW, 0x1030, 70000)
set_int32(LW, 0x1040, -70000)
set_uint64(LW, 0x1050, 1234567)
set_int64(LW, 0x1060, -1234567)
set_float(LW, 0x1070, 12.5)
set_double(LW, 0x1080, 12.5)
print(get_uint16(LW, 0x1014))
print(get_int16(LW, 0x1020))
print(get_uint32(LW, 0x1030))
print(get_int32(LW, 0x1040))
print(get_uint64(LW, 0x1050))
print(get_int64(LW, 0x1060))
print(get_float(LW, 0x1070))
print(get_double(LW, 0x1080))
end
例如用两个本地字保留完整 0xFFFFFFFF,不把它当成一个 Lua 非负整数:
local LW = 1
function write_large_unsigned_value()
set_uint16_ex(LW, 0x1090, {0xFFFF, 0xFFFF})
local high = get_uint16(LW, 0x1090)
local low = get_uint16(LW, 0x1091)
print(string.format("%04X%04X", high, low))
end
get_bit(vtype, addr)
set_bit(vtype, addr, value)
set_bit(vtype, addr, value, notify)
get_bit 返回 0 或 1。set_bit 的 value 只能是整数 0 或 1,成功无返回值。参数中的 addr 是相应变量地址,没有额外的位索引参数;在 LW/RW 字变量上,这两个接口读取或修改该字的第 0 位。
Modbus 类型 3/4 中,get_bit/set_bit 访问地址所指的单点,get_uint16/set_uint16 则访问连续 16 点;例如 set_uint16(3, 0x224, 1) 会把随后 15 点写为 0,单线圈应使用 set_bit(3, 0x224, 1)。类型 5/6 的 get_bit 读取字内 bit0,主站 set_bit(6, ...) 按已确认缓存合并后发送完整字,须先建立有效读回,不提供 PLC 原子掩码写。任意字内位及字段的辅助函数见专门示例。
| notify | 作用 |
|---|---|
| 0 | 当前写入不产生本地 on_update 通知,也不请求主动协议上传 |
| 1 | 默认值:正常变量更新通知,并请求协议通知 |
| 2 | 正常变量更新通知,不请求主动协议上传 |
主动协议上传指 DCBUS/DGUS 的自动上传,仍受工程“自动上传”设置及 set_notify 开关影响。notify=0/2 不会阻止 Modbus、FX、DVP、XC、XD 等主站向外部寄存器发送写命令。外部 PLC 后续真实应答或读回属于独立的缓存更新,不受此前静默写入的限制。需要操作一个 LW 字的其他位时,可先读取完整字,用 Lua 位运算修改,再用 set_uint16 写回:
local LW = 1
function on_init()
set_bit(LW, 0x1100, 1, 2)
print(get_bit(LW, 0x1100))
local value = get_uint16(LW, 0x1101)
set_uint16(LW, 0x1101, value | (1 << 3))
end
PLC 位软元件使用该协议自己的位地址,不把上面的本地字位运算当作 PLC 相邻位的批量写入。
get_string(vtype, addr)
set_string(vtype, addr, text)
get_string 从起始字地址读取最多 64 个字,即 128 字节,遇到首个零字节结束并返回字符串;接近地址末端时只读取剩余范围。没有长度参数。读不到的部分不会继续读取,因此返回空字符串或较短字符串也不能证明外部设备在线。
set_string 接收最多 127 字节文本,加零结尾并按完整字对齐后写入,成功无返回值。限制按编码后的字节数计算,不是字符个数;UTF-8 中文通常占多个字节。按“前一字符在字的高字节、后一字符在低字节”的顺序写入,例如 AB 对应字 0x4142。不要在普通文本中插入零字节,否则读取会在该处结束。
local LW = 1
function on_init()
set_string(LW, 0x1200, "Hello")
local text = get_string(LW, 0x1200)
print(text)
end
根据最长文本预留完整地址范围。PLC 字符串写入还受该驱动支持的数据区和单次容量限制;不是所有 PLC 软元件都支持字符串。
set_uint16_ex(vtype, addr, values)
set_array(vtype, addr, values)
两者功能相同:values 为从下标 1 开始、没有空洞的整数表,长度为 1~2000,每项表示一个 16 位字,按连续地址写入。每项请使用 0~65535 的整数;成功无返回值。它们不是 8 位字节数组接口,没有对应的 get_array 原生接口。
local LW = 1
function on_init()
set_uint16_ex(LW, 0x1014, {9, 0, 9})
-- LW1014=9,LW1015=0,LW1016=9。
set_array(LW, 0x1300, {0x1234, 0x5678})
for i = 0, 1 do
print(get_uint16(LW, 0x1300 + i))
end
end
字表提交原始 16 位字,不执行单值数值接口的 16 位整序交换;超范围表项当前会截断为 UINT16,应在调用前检查。Modbus 线圈字表每项覆盖 16 点,{1, 0, 1} 表示 48 点,不是三个单点;具体保尾及分帧规则见专门示例。
数组跨度不能越过地址末端,PLC 后端也可能因设备区、只读范围或缓存容量拒绝。需要发送原始字节表时使用 uart_send,不要把它与寄存器字数组混用。
select_slave(slave_index)
start_read(slave_index, vtype, addr, count)
slave_index 是工程配置中的从站索引,从 0 开始,不是设备通信站号。默认选择索引 0;例如第二个配置从站的站号是 7,仍应使用 select_slave(1)。索引必须为已配置的 0~7,FX 只支持 0;非法选择会抛错误并保留此前选择。选择影响后续数值、位、字符串及数组读写,LW/RW 仍使用本地数据区。
start_read 登记持续轮询范围,成功无返回值,不同步返回数据。通常在脚本顶层或 on_init 登记一次,换页和通信重配会恢复登记,不需要每次 on_run 重复登记。
count 为整数 1~65535,且 addr + count <= 65536;最多保留 16 个不同的“从站索引 + 类型 + 起始地址”范围,同一起点再次调用会修改数量。Modbus 字区以 16 位字计数;Modbus 类型 3/4 延续寄存器桥接语义,每个登记字覆盖最多 16 个位。LW/RW 不登记外部轮询,也不消耗范围槽位。PLC 仍受工程地址范围、设备原生元素宽度和驱动容量限制。
local HOLDING = 6
function on_init()
select_slave(0)
start_read(0, HOLDING, 100, 10)
set_run_cycle(100)
end
function on_run(screen)
local value = get_uint16(HOLDING, 100)
print("page", screen, "cached value", value)
end
没有注册名为 poll_register 或 stop_read 的 Lua 接口。脚本关闭或重载会清理旧脚本的预读范围,控件自身的轮询独立保留。首次预读登记成功不代表已经收到从站应答。
脚本可定义 on_update(slave, vtype, addr)。运行库在可读缓存更新后调用;slave 是从站索引,本地 LW/RW 为 0,addr 是实际更新的地址。使用相应 get_* 读取最新值:
local LW = 1
function on_update(slave, vtype, addr)
if vtype == LW and addr == 0x1014 then
local value = get_uint16(LW, addr)
print("temperature", value)
end
end
相同值通常不重复通知,外部源首次有效零值也会通知;同一地址分发前的多次变化可能合并为一次。多字值可能按组成它的多个寄存器通知。回调中同步写变量不会递归触发新的 on_update,回调返回值不能撤销写入。
set_notify(enable)
enable 必须是整数 0 或 1,成功无返回值。默认开启;set_notify(0) 关闭 DCBUS/DGUS 自动上传,set_notify(1) 恢复后续自动上传。它作用于 Lua set_*、控件通知及系统复制触发的自动上传,仍需在工程中开启“自动上传”。
local LW = 1
function update_demo_value()
set_notify(0)
set_uint16(LW, 0x2100, 123)
set_notify(1)
end
关闭时仍更新本地值、控件显示及相应 on_update;恢复后不会补发关闭期间的数据。脚本关闭、重载或加载失败时,运行库会在脚本资源和终结器清理完成后恢复默认开启。
此接口不是整个串口的停发开关。 它不停止协议应答、PLC 主站轮询、主动 uart_send、独立第二串口或串口下载。Modbus、FX、DVP、XC、XD 等外部寄存器的 set_* 仍进入主站写队列;要暂停这类发送,应停止或限制脚本中的写操作。暂停定时写入见定时器函数。
LW 常量:在脚本中先写 local LW = 1,或者直接传整数 1。set_float 或 set_double。get_string 传长度、为 set_uint16 多传通知参数:签名不支持这些参数。local ok, err = pcall(set_uint16, 1, 0x1014, 9)
if not ok then
print("write failed", err)
end