- 1. 0. 基础:自动生成的 main.lua
- 2. 1. 常用回调函数(10 个)
- 3. 2. 读写寄存器函数(32 个)
- 4. 2.0 先说两个关键机制(所有 set/get 通用)
- 5. 2.1 通信控制
- 6. 2.2 位操作
- 7. 2.3 数值读写(16/32/64 位)
- 8. 2.4 字符串与批量
- 9. 3. 绘图函数(10 个)
- 10. 4. 绘图实例:switch 表驱动
这是 VisualHMI 平台 Lua 脚本的完整 API 手册:10 个系统回调 + 32 个读写寄存器函数 + 10 个绘图函数,共 52 个接口。写脚本前先翻这篇,比逐个翻教程快。平台基于 Lua 5.3。
0. 基础:自动生成的 main.lua
菜单 工程→脚本编程 默认生成 main.lua,自动带协议对应的数据类型定义:
ENCRYPT_ = 0 -- LUA脚本加密开关 -- 数据类型定义(随协议变化,以下为 Modbus) VT_LW = 1 -- 内部变量 VT_RW = 2 -- FLASH掉电存储 VT_0x = 10 -- 线圈 VT_1x = 11 -- 输入点(离散输入) VT_3x = 12 -- 输入寄存器 VT_4x = 13 -- 保持寄存器 function on_init() end function on_run(screen) end function on_update(slave,vtype,addr) end function on_draw(screen_id,control_id) end
FX3U 协议下还会有 VT_M(内部继电器)、VT_D(D寄存器)等类型。on_update 里的 vtype、get/set 函数第一个参数都用这些常量。
1. 常用回调函数(10 个)
| 回调 | 触发时机 | 要点 |
|---|---|---|
on_init() |
系统加载 LUA 后立即执行一次 | 初始化、dofile 加载其他 lua、写初值 |
on_run(screen) |
每个主循环周期自动调用 | 核心周期调度。禁止 delay_ms/长循环/网络同步/内部 set_run_cycle();Modbus 主站时别高频写从机(总线堵塞) |
on_update(slave,vtype,addr) |
寄存器/变量值变化时触发 | 数据驱动不轮询。串口/Modbus 主站写入、on_update 内 set_xxx 不触发(防递归);可用全局 EN_ON_UPDATE_API_CB 控制开关 |
on_screen_change(screen) |
画面切换完成后 | 初始化/状态同步/资源加载 |
on_press(state,x,y) |
触摸状态变化,每 100ms 最多一次 | state: 0抬起/1按下/2长按(按下只触发一次);底层坐标,点空白也触发 |
on_usb_inserted(driver) |
U 盘插入识别 | driver 为盘符,M 系列是 “2:”,用全局变量记录 |
on_usb_removed() |
U 盘拔出 | 清盘符全局变量 |
on_sd_inserted(dir) |
SD 卡插入识别 | dir 盘符,M 系列是 “1:” |
on_sd_removed() |
SD 卡拔出 | 清盘符全局变量 |
on_parse_timestamp(screen,control,timestamp) |
告警/数据/操作记录表格时间字段格式化 | control 必须≠0;配 make_datetime(timestamp) 返回自定义时间串 |
2. 读写寄存器函数(32 个)
2.0 先说两个关键机制(所有 set/get 通用)
机制一:get_xxx() 是零通信开销的。get 系列全部从 HMI 本地缓存(内存镜像)读,不产生串口帧。HMI 后台任务按工程配置的轮询周期自动从 PLC 读通信变量(如 Modbus 的 VT_3x/VT_4x)并缓存。画面控件绑定了某地址,该地址就自动进轮询列表;脚本要读没被工程引用的地址,用 start_read 显式请求同步。
机制二:set_xxx() 不一定发串口帧。只有两个条件同时满足才主动发报文:①HMI 是主机模式(Modbus Master/DCBUS/XGUS);②串口通知没被 set_notify(0) 禁止。从机模式下 set 只更新本地镜像。
2.1 通信控制
| 函数 | 参数 | 说明 |
|---|---|---|
set_notify(enable) |
0禁止/1使能(默认) | 全局串口发送通知开关。set_notify(0) 后 set_xxx 不发串口指令,改完恢复 set_notify(1) |
select_slave(slave_id) |
从机索引 0 起 | 多从机模式下切换后续 get/set 访问的从机。slave_id 是工程从机列表数组下标,不是 Modbus 站号 |
set_endian(en) |
0大端(默认)/1小端 | 多字节数据(uint16/32/float)与从机交换时的字节序。仅通信协议涉及多字节时生效 |
start_read(index,vtype,addr,quantity,cycle,cycle_run,mode) |
index 0~127;quantity 1~120;cycle 轮询倍数(默认0=每周期);cycle_run 周期内第几次(0-based);mode 0持续/1仅一次 | 主机模式后台自动轮询。无返回值,数据用 get_xxx 读缓存。mode=1 需先 create_resp_que() |
stop_read(index) |
任务索引 | 停止指定后台读取任务,缓存保留最后值 |
stop_all_read() |
– | 停掉所有脚本启动的读取任务 |
set_auto_read(en) |
1启用(默认)/0禁止 | 画面绑定变量自动轮询的总开关。0 后完全由 start_read 接管 |
create_resp_que() |
– | 创建响应队列,配合 start_read(mode=1) 做单次按需读取 |
on_cmd_resp(slave,vtype,addr,count,ret,wr) |
ret 0成功/1异常;wr 0读/1写 | 主机模式通信结果异步回调,收到响应或超时触发。判断单次读写成败 |
set_slave_site(idx,slave_id) |
idx 从机索引;slave_id 新站号(Modbus 1~247) | 运行时动态改从机站号,适应现场组网 |
2.2 位操作
| 函数 | 参数 | 说明 |
|---|---|---|
set_bit(vtype,addr,value,count) |
value 16位无符号,低 count 位对应目标位(bit0→addr,bit1→addr+1…);count 选填 1~16 | 批量位写入。Modbus 线圈、FX3U 的 X/Y/S/M 都行。一次通信写多个开关 |
get_bit(vtype,addr) |
– | 读单一位,返回 0/1。从本地缓存读,零通信开销 |
2.3 数值读写(16/32/64 位)
| 函数 | 数值范围 | 地址跨度 |
|---|---|---|
set/get_uint16(vtype,addr,value) |
0~65535,超出截断 & 0xFFFF | 1 个寄存器 |
set/get_int16(vtype,addr,value) |
-32768~+32767,超出截断 & 0xFFFF | 1 个寄存器 |
set/get_uint32(vtype,addr,value) |
0~4294967295,截断 & 0xFFFFFFFF | 2 个寄存器 |
set/get_int32(vtype,addr,value) |
-2^31~2^31-1 | 2 个寄存器 |
set/get_uint64(vtype,addr,value) |
0~2^64-1 | 4 个寄存器 |
set/get_int64(vtype,addr,value) |
-2^63~2^63-1 | 4 个寄存器 |
set/get_float(vtype,addr,value) |
IEEE 754 单精度 | 2 个寄存器 |
set/get_double(vtype,addr,value) |
IEEE 754 双精度 | 4 个寄存器 |
所有 get 系列读本地缓存;set 系列通信触发看「机制二」。
2.4 字符串与批量
| 函数 | 参数 | 说明 |
|---|---|---|
set_string(vtype,addr,str) |
str 最大 2K 字节,UTF-8 或 GBK | 写字符串到地址序列 |
get_string(vtype,addr,len) |
len 选填,默认 128 字节,最大 2048 | 读字符串,自动在 截断 |
set_uint16_ex(vtype,addr,value1,...,valueN) |
最多 120 个值 | 可变参数批量写连续寄存器,适合固定参数集 |
set_array(vtype,addr,buff) |
buff 为 Lua table(word 数组),最多 120 字 | table 批量写,适合程序化生成/动态数据。与 set_uint16_ex 区别在传参方式 |
3. 绘图函数(10 个)
全部 draw_xxx 必须在 on_draw(screen_id,control_id) 回调里调用才生效,控件 ID 必须 ≠ 0。图层按控件 Z 轴(编辑器叠放顺序)管理,靠判断 control_id 分层绘制。主动刷新调 redraw()。
| 函数 | 参数 | 说明 |
|---|---|---|
set_pen_color(color) |
RGB565:高5位R(0~31)/中6位G(0~63)/低5位B(0~31) | 设置画笔(前景)颜色。红 0xF800、绿 0x07E0、蓝 0x001F、白 0xFFFF、黑 0x0000 |
draw_line(x0,y0,x1,y1,width) |
width 1~10 | 画直线,颜色取当前画笔 |
draw_rect(x0,y0,x1,y1,fill) |
fill 1填充/0边框 | 左上角+右下角坐标 |
draw_rect_alpha(x0,y0,x1,y1,alpha) |
alpha 0~255(0透明/255不透明) | 半透明实心矩形,遮罩层常用 |
draw_circle(x,y,r,fill) |
fill 0实心/非0空心(值作线厚) | 圆心+半径 |
draw_ellipse(x0,y0,x1,y1,fill) |
fill 0实心/非0空心 | 外接矩形定义椭圆 |
draw_image(image_id,frame_id,dstx,dsty,width,height,srcx,srcy) |
image_id 查 build/image.xml;frame_id 动画帧(非动画=0) | 绘制图片,支持缩放+裁剪。image_id 在工程 build 目录 image.xml 里查 |
draw_text(text,x,y,w,h,font_id,size,color,align,charcode) |
align 0左/1中/2右;charcode 0=UTF-8(默认)/1=GBK | 区域文字绘制,支持多字节字符 |
draw_surface(surface,x,y,w,h,srcx,srcy) |
surface 为画面/画布资源 | 画面裁剪显示,多图层合成用 |
4. 绘图实例:switch 表驱动
源文所有绘图示例都是一个套路:on_update 读按钮键值 → redraw() → on_draw 里按键值查 switch 表选绘制函数。以画线+画圆为例:
draw_type = 0
mode = { line = 1, rect = 2, rect_alpha = 3, circle = 4, ellipse = 5, imageId = 6, text = 7 }
function on_update(slave,vtype,addr)
if addr == 0x1000 then
draw_type = get_uint16(VT_LW, addr) -- 字设置按钮键值
redraw()
end
end
function on_draw(screen_id, control_id)
local switch = {
[mode.line] = function(control)
if screen_id == 0 and control == 1 then
set_pen_color(0xFFE0) -- 黄色
draw_line(225, 253, 405, 253)
set_pen_color(0xF800) -- 红色
draw_line(508, 128, 508, 378, 5)
end
end,
[mode.circle] = function(control)
if screen_id == 0 and control == 1 then
draw_circle(300, 253, 100, 0) -- 实心圆
draw_circle(450, 253, 150, 1) -- 空心圆,线厚1
end
end,
}
if switch[draw_type] then switch[draw_type](control_id) end
end
整理自 广州大彩科技 VisualHMI 开发文档(hmi-doc.gz-dc.com)LUA 教程「Lua 脚本API函数接口」,版权归大彩科技所有。
发表回复