内容目录
本文目录
- 1. 1. 五大回调总览
- 2. 2. on_init() 初始化
- 3. 2.1 加载其他 lua 文件
- 4. 2.2 加载系统参数(掉电存储)
- 5. 2.3 初始化 Flash 参数(首次上电)
- 6. 2.4 初始化 PLC/驱动板
- 7. 3. on_run(screen) 周期回调
- 8. 4. on_press(state,x,y) 触摸回调
- 9. 5. on_update(slave,vtype,addr) 变量修改回调
- 10. 6. on_screen_change(screen) 画面切换回调
系统回调函数是 LUA 和 HMI 内核的”钩子”:特定事件发生时系统自动调用。掌握这 5 个回调,就掌握了 LUA 编程的主干。
1. 五大回调总览
| 函数 | 触发时机 | 用途 |
|---|---|---|
| on_init() | 上电加载 LUA 后立即执行一次 | 初始化:加载模块、初始化参数、发指令给 PLC |
| on_run(screen) | 主循环周期调用(set_run_cycle 设周期) | 周期任务:实时数据、状态轮询 |
| on_press(state,x,y) | 触摸状态变化(每 100ms 最多一次) | 自定义待机、触摸检测 |
| on_update(slave,vtype,addr) | 变量被修改时(用户操作或脚本) | 数据驱动逻辑:值变化响应 |
| on_screen_change(screen) | 画面切换完成后 | 画面初始化/状态同步 |
2. on_init() 初始化
2.1 加载其他 lua 文件
function on_init()
dofile("sysParam.lua")
end
2.2 加载系统参数(掉电存储)
系统参数(触摸音 SysCfg0、语言 SysLang、音量 SysSndVol、背光等)掉电存储:
function on_init() set_uint16(VT_LW, 0x011B, (1 << 1)) -- 选择加载掩码, bit1=多语言 set_uint16(VT_LW, regAddr.sysParamCtrl, 0x5502) update_system() end
2.3 初始化 Flash 参数(首次上电)
判断 RW 区标志位,不等于特定值就执行初始化:
function on_init()
local fst = get_uint16(VT_RW, 0x7FFF)
if fst ~= 0x55AA then
set_uint16(VT_LW, regAddr.sysCfg0, 1)
set_uint16(VT_LW, regAddr.sysLang, 0)
set_uint16(VT_LW, regAddr.sysBLLevel, 100)
set_uint16(VT_LW, regAddr.sysSndVol, 80)
set_uint16(VT_LW, regAddr.sysParamSlct, (1 << 3)|(1 << 2)|(1 << 1)|(1 << 0))
set_uint16(VT_LW, regAddr.sysParamCtrl, 0x5501)
update_system()
set_uint16(VT_RW, 0x7FFF, 0x55AA)
end
end
2.4 初始化 PLC/驱动板
function on_init() set_uint16(VT_4x, 0x0000, 0x55AA) -- 写保持寄存器 set_bit(VT_0x, 0x1000, 0x0001) -- 置线圈 end
3. on_run(screen) 周期回调
由系统每个主循环周期自动调用,做定期更新逻辑。周期用 set_run_cycle(ms) 设置:
function on_run(screen)
local start = get_uint16(VT_4x, 0x1000) -- 开机状态
local dstVol = get_uint16(VT_4x, 0x1001) -- 设置电压
local curVol = get_uint16(VT_4x, 0x1002) -- 当前电压
local online = get_uint16(VT_4x, 0x01A3) -- 在线状态位掩码
if dstVol > curVol and start == 1 and (online & 0x01 == 1) then
set_uint16(VT_4x, 0x1003, 1) -- 设置频率
end
end
function on_init()
set_run_cycle(1000) -- on_run 1s 回调一次
end
⚠️ on_run 三大禁忌:①高频写从机寄存器(HMI 作 Modbus 主站时)会造成总线堵塞;②不能用 delay_ms()、长循环、网络同步请求;③严禁在 on_run 内部调用 set_run_cycle()(可能死锁)。
4. on_press(state,x,y) 触摸回调
全局触摸事件,state:1=按下(仅触发一次)、2=长按、0=抬起。提供底层坐标,不依赖控件,点击空白也触发。典型应用:自定义待机——配 on_timer 做”无触摸自动进节能”。
function on_press(state,x,y)
_EN_ON_UPDATA_API_ = 0
if state == 0 then
std.init() -- 触摸后重置待机计时
end
_EN_ON_UPDATA_API_ = 1
end
5. on_update(slave,vtype,addr) 变量修改回调
数据驱动:用户操作或脚本修改受监控寄存器时自动触发,无需轮询。参数:slave=站号(0 起)、vtype=变量类型(VT_4x/VT_0x/VT_LW 等)、addr=寄存器地址。
不会触发 on_update 的场景:外部设备通过串口直接写从机寄存器;on_update 内部调用 set_xxx(防递归自动屏蔽)。
防止其他回调的 set_xxx 触发 on_update,用全局开关:
_EN_ON_UPDATE_API_CB_ = 1 function on_init() _EN_ON_UPDATE_API_CB_ = 0 set_uint16(VT_LW, 0x1000, 0x55AA) _EN_ON_UPDATE_API_CB_ = 1 end function on_update(slave, vtype, addr) if _EN_ON_UPDATE_API_CB_ == 0 then return end -- 业务逻辑 end
6. on_screen_change(screen) 画面切换回调
每次画面切换完成后调用,参数 screen=目标画面 ID。用于画面初始化、状态同步:
function on_screen_change(screen)
if screen == 1 then
set_bit(VT_0x, 0x0000, 1) -- 进入画面1时置位
end
end
回调函数不能直接调用(on_draw 等),由系统触发。on_update 的「数据驱动」模型效率远高于轮询——值变了才响应,这是 VisualHMI 写逻辑的核心思路。
整理自 广州大彩科技 VisualHMI 开发文档(hmi-doc.gz-dc.com)LUA 教程「系统回调函数」,版权归大彩科技所有。
发表回复