系统回调是 LUA 和 HMI 内核之间的事件인터페이스:内核在特定时机自动调你的函数,你不用轮询、不用自己触发。搞懂每个回调的触发时机和限制,是写出稳定스크립트的前提。
1. 回调总表
| 回调 | 触发时机 | 用途 |
|---|---|---|
on_init() | 上电불러오기后执行一次 | dofile 불러오기模块、初始化매개변수/PLC/驱动板 |
on_run(screen) | 周期执行(set_run_cycle 设定周期) | 核心调度入口,周期性任务 |
on_press(state,x,y) | 触摸事件,100ms 最多一次 | 按键处理、空闲待机 |
on_update(slave,vtype,addr) | 변수值变化 | 데이터驱动逻辑(推荐优先用) |
on_screen_change(screen) | 화면전환后 | 화면初始化、状态同步 |
2. on_run:周期调度(注意别卡死)
on_run 是周期回调,里面干活的时长必须远小于周期。三个禁忌:
- Modbus RTU Master 高频쓰기易总线堵塞——on_run 里别每秒狂发写帧
- 不可用 delay_ms、长循环、네트워크同步——阻塞主循环,화면全卡
- 严禁 set_run_cycle 死锁——回调里改周期可能造成永不触发
function on_init() set_run_cycle(1000) -- 设定 1 秒周期 end function on_run(screen) -- 每秒做一次的事情:状态轮询、超时判断 end
3. on_press:触摸回调与空闲待机
on_press(state, x, y),state:0=抬起、1=按下、2=长按。每 100ms 最多触发一次。典型用途是空闲待机节能:一段时间没触摸自动熄屏/跳主页。
_IDLE_TIMEOUT = 300000 -- 5分钟无操作
_idle_tick = 0
function on_press(state, x, y)
_idle_tick = 0 -- 有触摸就重置计时
end
function on_run(screen)
_idle_tick = _idle_tick + 1000 -- 假设周期1s
if _idle_tick >= _IDLE_TIMEOUT then
set_screen(0) -- 跳回主화면
_idle_tick = 0
end
end
4. on_update:데이터驱动(优先用这个)
on_update(slave, vtype, addr) 在변수值变化时触发,是데이터驱动모드——比 on_run 轮询省자료。三个特性必须知道:
- 外部시리얼 포트/Modbus 마스터쓰기不触发——只对 HMI 内部변수变化生效
- on_update 内调 set_xxx 被屏蔽——防无限递归,改值不会再次触发
- 全局변수 _EN_ON_UP데이터_API_ 控制开关——置 0 可临时禁用,批量初始化时用
_EN_ON_UP데이터_API_ = 0 -- 初始化期间关回调
-- ... 批量写레지스터 ...
_EN_ON_UP데이터_API_ = 1 -- 开回回调
function on_update(slave, vtype, addr)
if vtype == VT_LW then
if addr == 0x1000 then
-- LW1000 变化了,处理业务
end
end
end
5. on_screen_change:화면전환后初始化
화면전환完成后触发,做该화면的初始化、状态同步、자료불러오기——比在切屏前处理更稳。
四个坑:①on_run 里严禁 delay_ms/长循环,会卡死主循环;②Modbus 마스터别在 on_run 高频写,总线堵塞没商量;③on_update 里 set_xxx 不会再次触发回调,别指望链式触发;④批量初始化레지스터前把 _EN_ON_UP데이터_API_ 置 0,防回调风暴。
整理自 广州大彩科技 VisualHMI 개발문서(hmi-doc.gz-dc.com)LUA 튜토리얼「系统回调」,版权归大彩科技所有。
답글 작성