# 宏指令(全部,逐行注释) > 摘自同目录 `开发主文件.md` 第 6 章,直接复制到 EB Pro 宏编辑器。 ## 6.0 工程实际清单(2026-10-27 核对,依据 EB Pro「宏指令」窗口) > 现工程 `unitouch1025.cmtp` 共 **50 条**(ID 000~050,**缺 031**)。 > `{I}` = 当 HMI 启动时即执行一次;`{P}` = **周期执行**;无标记 = 由按钮/窗口事件触发。 > 本表是“以工程为准”的基准,下文 6.1 起的正文若与本表冲突,**以本表为准**。 | ID | 宏名 | 条件 | 用途 | 文档状态 | |---|---|---|---|---| | 000 | `main-init` | I | 开机初始化 `LW-0/1/2`、页面位图 `LW-70~73`、`RW-61` | 有正文 | | 001~007 | `btn-y1`~`btn-y7` | — | Y 页签导航(权限 + 页面存在位图) | 有正文 | | 008~011 | `btn-x1`~`btn-x4` | — | X 页签导航 | 有正文 | | 012 | `btn-login-index` | — | 索引登入 + 内联提示映射 | 有正文 | | 013 | `macro_13` | — | **空宏**:只有 `macro_command main()` / `end macro_command`,无任何语句;无执行条件、非周期、非开机 | ✅ 已核对:**可删** | | 014 | `close-msg` | — | 关 11 号无权限窗 | 有正文 | | 015~017 | `open-time` / `set-time` / `close-time` | — | 修改时间 | 有正文 | | 018 | `logout` | — | 注销并回 10 号窗 | 有正文 | | 019 | `user-open` | — | 开 14 号用户管理窗 | 有正文 | | 020~027 | `usr-init`/`usr-back`/`usr-add`/`usr-delete`/`usr-delete-ok`/`usr-delete-cancel`/`usr-setlevel`/`usr-setpwd` | — | 用户管理各种命令 | 有正文(模板) | | 028~029 | `about-open` / `about-close` | — | 关于窗 | 有正文 | | 030 | `usr-getlevel` | — | 按索引读权限 | 有正文(模板) | | — | (031 已删除,工程内无此 ID) | — | — | — | | 032 | `close-nopage` | — | 关 16 号“无内容”窗 | 有正文 | | 033~035 | `admin-close` / `admin-login` / `admin-open` | — | 超管登录弹窗 | 有正文 | | 036 | `line-ab-switch` | — | A/B 线切换(仅 role=1) | 有正文 | | 037 | `net-apply` | I | 网络参数套用(HMI + 设备 4/5 IP) | 有正文(10-27 已加 IP 保护) | | 038 | `net-read` | — | 系统网络值 → 暂存 `RW` | 有正文 | | 039~041 | `x2y2-focus-area1`~`area3` | — | X2Y2 三区聚焦 → `LW-50` = 30/31/32 | 已补录(6.2) | | 042 | `IO切换上料` | — | IO 组索引 9 → `LW-300`,窗口 158 | 已补录(6.2) | | 043 | `x2y2-focus-area-close` | — | 关区域弹窗(`LW-50=0`) | 已补录(6.2) | | 044 | `IO切换清洗` | — | IO 组索引 15 → `LW-300`,窗口 168 | 已补录(6.2) | | 045 | `IO切换制丸` | — | IO 组索引 1 → `LW-300`,窗口 151 | 已补录(6.2) | | 046 | `上料参数` | — | 窗口 210(与「清洗-点动」重名,存疑) | 已补录(6.2) | | 047 | `温度监控` | P(1s) | 读 16 个 REAL(`HMI_EM02.Temperature_PV`)→ `LW-200` | 已补录(6.2) | | 048 | `屏蔽通讯异常提示` | P(100ms) | 周期置 ON `LB-11960~11967`(设备 1~8 的 “Device No Response”) | 已补录(6.2) | | 049 | `出条温度监控` | P(1s) | 读 10 个 REAL(`HIKMICRO_Temp_R`)→ `LW-240` | 已补录(6.2) | | 050 | `IO` | P(100ms) | 按 `LW-300` 索引读 `PLC.Tags.Table.Local_*`(1~19) | ✅ 已补全(20~24 注释) | ### 6.0.1 与旧文档的差异(已确认) 1. **区域弹窗宏名不对**:实际是 `x2y2-focus-area1~3` + `x2y2-focus-area-close`,旧文档的 `area-1~4` / `area-close` 作废;且**只有 3 个区域**,没有 area-4(与“4 区并 3 区”一致)。 2. **48 号宏 `屏蔽通讯异常提示` 是周期执行(P)**,不是开机一次;它把 `LB-11960~11967` 八台设备全屏蔽,不是文档写的 63/64 两台。 3. **7 条宏文档完全没有**:`macro_13`、`IO切换上料`、`IO切换清洗`、`IO切换制丸`、`上料参数`、`温度监控`、`出条温度监控`、`IO`(含 3 条周期温度宏)。 4. **ID 031 缺失**(工程里已删除,文档无记录)。 5. `macro_13`(ID 013)是**空宏**(无语句、无执行条件),建议直接删除,不留占位。 ### 6.0.2 核对状态(2026-10-27 收尾) | 项 | 状态 | | --- | --- | | 38 条原有正文 | 与工程一致,未发现改动 | | 039/040/041/043(区域弹窗) | ✅ 已补录:`win` = 30 / 31 / 32,关闭写 0 | | 042/044/045(IO 切换) | ✅ 已补录:写 `LW-300`=组索引、`LW-2`=窗口 | | 046(上料参数) | ✅ 已补录,但**窗口 210 与「清洗-点动」重名,存疑** | | 047/049(温度) | ✅ 已补录,但 **float 拷贝长度与注释不符**(见 6.2.1) | | 048(屏蔽通讯) | ✅ 已补录:100 ms 周期压 8 个位 | | 050(IO) | ✅ 已补全:1~19 有效,20~24 为制丸2 预留(注释) | | 013(macro_13) | ✅ 空宏,可删 | | 000(main-init) | ✅ 已核对:仍为 `127/18/127/18` + `RW-61=1`,未变;说明 130~282 新页不走 X/Y 导航 | ## 6.1 宏正文(逐行注释) > 命名:导航 = `btn-*`、登录 = `main-init`/`btn-login-index`/`logout`、管理员登录 = `admin-open`/`admin-login`/`admin-close`、用户管理 = `user-open` + `usr-*`(你的工程删除类为 `usr-delete*`)、关于窗 = `about-open`/`about-close`、时间 = `open-time`/`set-time`/`close-time`、弹窗 = `close-msg`/`close-nopage`。 > **登录提示已内联**:`LW-101` 结果码 → `LW-261` 的映射直接写在 `btn-login-index`/`admin-login` 内,零延迟、不轮询、不依赖宏编号。`net-apply` 用宏属性「当 HMI 启动时即执行一次」。 > 权限判定统一用 `LW-9222` 的类别位(`GETBIT` 取值 + `if`,不用 `and`/`&`)。 **`main-init`**(开机执行一次) ``` macro_command main() // 宏入口:HMI 启动时执行一次 short x = 1 // X 初值 = 1 short y = 1 // Y 初值 = 1 short win = 0 // 目标窗口号初值 = 0(不切窗) short r1 = 127 // X1 段存在位图:bit0=Y1…bit6=Y7,1=有内容(X1 全有 = 127) short r2 = 18 // X2 段:只留 Y2/Y5(缺 Y1/Y3/Y4/Y6/Y7)→ 2+16=18 short r3 = 127 // X3 段:Y1~Y7 全有(X3Y6 已启用)→ 127 short r4 = 18 // X4 段:只留 Y2/Y5(缺 Y1/Y3/Y4/Y6/Y7)→ 2+16=18 short one = 1 // 常量 1(默认制丸线别) SetData(x, "Local HMI", LW, 0, 1) // X → LW-0 SetData(y, "Local HMI", LW, 1, 1) // Y → LW-1 SetData(win, "Local HMI", LW, 2, 1) // 窗口号 0 → LW-2(不触发切窗) SetData(r1, "Local HMI", LW, 70, 1) // X1 位图 → LW-70 SetData(r2, "Local HMI", LW, 71, 1) // X2 位图 → LW-71 SetData(r3, "Local HMI", LW, 72, 1) // X3 位图 → LW-72 SetData(r4, "Local HMI", LW, 73, 1) // X4 位图 → LW-73 SetData(one, "Local HMI", RW, 61, 1) // 开机默认制丸线别 = A(只有人工切换才变 B) end macro_command // 宏结束 ``` **导航宏说明**:先查权限(`LW-9222` 类别位)→ 再查当前 Y 页面是否存在(`LW-70`~`73` 位图)→ 有内容才切窗,无内容弹 16 号窗。 **`btn-x1`**(X1 配料/上料 · 权限 A/B/C) ``` macro_command main() // 宏入口:按下 X1 按钮时执行 short cls = 0 // 当前用户类别位(读 LW-9222) short x = 1 // 本按钮固定切到 X=1 short y = 0 // 运行时读回的当前 Y(1~7) short win = 0 // 计算出的目标窗口号 short ok = 0 // 权限通过标志:1=放行 short bv = 0 // 页面存在标志:1=有内容 short vpm = 0 // X1 段页面存在位图(LW-70) short pop = 1 // 弹窗置位常量 1 short bA = 0 // 类别 A 位(工程师) short bB = 0 // 类别 B 位(管理员) short bC = 0 // 类别 C 位(上料) GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师) GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员) GETBIT(cls, bC, 2) // 取 bit2 → bC(C 上料) if bA == 1 then // 含类别 A? ok = 1 // 权限通过 end if // 结束判断 if bB == 1 then // 含类别 B? ok = 1 // 权限通过 end if // 结束判断 if bC == 1 then // 含类别 C? ok = 1 // 权限通过 end if // 结束判断 if ok == 1 then // 权限通过 → 继续查页面 GetData(y, "Local HMI", LW, 1, 1) // 读当前 Y → y GetData(vpm, "Local HMI", LW, 70, 1) // 读 X1 段存在位图 → vpm if y == 1 then // 当前 Y=1? GETBIT(vpm, bv, 0) // 取位 0(Y1)→ bv end if // 结束判断 if y == 2 then // 当前 Y=2? GETBIT(vpm, bv, 1) // 取位 1(Y2)→ bv end if // 结束判断 if y == 3 then // 当前 Y=3? GETBIT(vpm, bv, 2) // 取位 2(Y3)→ bv end if // 结束判断 if y == 4 then // 当前 Y=4? GETBIT(vpm, bv, 3) // 取位 3(Y4)→ bv end if // 结束判断 if y == 5 then // 当前 Y=5? GETBIT(vpm, bv, 4) // 取位 4(Y5)→ bv end if // 结束判断 if y == 6 then // 当前 Y=6? GETBIT(vpm, bv, 5) // 取位 5(Y6)→ bv end if // 结束判断 if y == 7 then // 当前 Y=7? GETBIT(vpm, bv, 6) // 取位 6(Y7)→ bv end if // 结束判断 if bv == 1 then // 该页面有内容? SetData(x, "Local HMI", LW, 0, 1) // X=1 → LW-0 win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1) SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗) else // 该页面无内容 SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗 end if // 结束判断 else // 权限不通过 SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗 end if // 结束判断 end macro_command // 宏结束 ``` **`btn-x2`**(X2 上料清洗 · 权限 A/B/C) ``` macro_command main() // 宏入口:按下 X2 按钮时执行 short cls = 0 // 当前用户类别位(读 LW-9222) short x = 2 // 本按钮固定切到 X=2 short y = 0 // 运行时读回的当前 Y(1~7) short win = 0 // 计算出的目标窗口号 short ok = 0 // 权限通过标志:1=放行 short bv = 0 // 页面存在标志:1=有内容 short vpm = 0 // X2 段页面存在位图(LW-71) short pop = 1 // 弹窗置位常量 1 short bA = 0 // 类别 A 位(工程师) short bB = 0 // 类别 B 位(管理员) short bC = 0 // 类别 C 位(上料) GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师) GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员) GETBIT(cls, bC, 2) // 取 bit2 → bC(C 上料) if bA == 1 then // 含类别 A? ok = 1 // 权限通过 end if // 结束判断 if bB == 1 then // 含类别 B? ok = 1 // 权限通过 end if // 结束判断 if bC == 1 then // 含类别 C? ok = 1 // 权限通过 end if // 结束判断 if ok == 1 then // 权限通过 → 继续查页面 GetData(y, "Local HMI", LW, 1, 1) // 读当前 Y → y GetData(vpm, "Local HMI", LW, 71, 1) // 读 X2 段存在位图 → vpm if y == 1 then // 当前 Y=1? GETBIT(vpm, bv, 0) // 取位 0(Y1)→ bv end if // 结束判断 if y == 2 then // 当前 Y=2? GETBIT(vpm, bv, 1) // 取位 1(Y2)→ bv end if // 结束判断 if y == 3 then // 当前 Y=3? GETBIT(vpm, bv, 2) // 取位 2(Y3)→ bv end if // 结束判断 if y == 4 then // 当前 Y=4? GETBIT(vpm, bv, 3) // 取位 3(Y4)→ bv end if // 结束判断 if y == 5 then // 当前 Y=5? GETBIT(vpm, bv, 4) // 取位 4(Y5)→ bv end if // 结束判断 if y == 6 then // 当前 Y=6? GETBIT(vpm, bv, 5) // 取位 5(Y6)→ bv end if // 结束判断 if y == 7 then // 当前 Y=7? GETBIT(vpm, bv, 6) // 取位 6(Y7)→ bv end if // 结束判断 if bv == 1 then // 该页面有内容? SetData(x, "Local HMI", LW, 0, 1) // X=2 → LW-0 win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1) SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗) else // 该页面无内容 SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗 end if // 结束判断 else // 权限不通过 SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗 end if // 结束判断 end macro_command // 宏结束 ``` **`btn-x3`**(X3 制丸 · 权限 A/B/D) ``` macro_command main() // 宏入口:按下 X3 按钮时执行 short cls = 0 // 当前用户类别位(读 LW-9222) short x = 3 // 本按钮固定切到 X=3 short y = 0 // 运行时读回的当前 Y(1~7) short win = 0 // 计算出的目标窗口号 short ok = 0 // 权限通过标志:1=放行 short bv = 0 // 页面存在标志:1=有内容 short vpm = 0 // X3 段页面存在位图(LW-72) short pop = 1 // 弹窗置位常量 1 short bA = 0 // 类别 A 位(工程师) short bB = 0 // 类别 B 位(管理员) short bD = 0 // 类别 D 位(制丸) GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师) GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员) GETBIT(cls, bD, 3) // 取 bit3 → bD(D 制丸) if bA == 1 then // 含类别 A? ok = 1 // 权限通过 end if // 结束判断 if bB == 1 then // 含类别 B? ok = 1 // 权限通过 end if // 结束判断 if bD == 1 then // 含类别 D? ok = 1 // 权限通过 end if // 结束判断 if ok == 1 then // 权限通过 → 继续查页面 GetData(y, "Local HMI", LW, 1, 1) // 读当前 Y → y GetData(vpm, "Local HMI", LW, 72, 1) // 读 X3 段存在位图 → vpm if y == 1 then // 当前 Y=1? GETBIT(vpm, bv, 0) // 取位 0(Y1)→ bv end if // 结束判断 if y == 2 then // 当前 Y=2? GETBIT(vpm, bv, 1) // 取位 1(Y2)→ bv end if // 结束判断 if y == 3 then // 当前 Y=3? GETBIT(vpm, bv, 2) // 取位 2(Y3)→ bv end if // 结束判断 if y == 4 then // 当前 Y=4? GETBIT(vpm, bv, 3) // 取位 3(Y4)→ bv end if // 结束判断 if y == 5 then // 当前 Y=5? GETBIT(vpm, bv, 4) // 取位 4(Y5)→ bv end if // 结束判断 if y == 6 then // 当前 Y=6? GETBIT(vpm, bv, 5) // 取位 5(Y6)→ bv end if // 结束判断 if y == 7 then // 当前 Y=7? GETBIT(vpm, bv, 6) // 取位 6(Y7)→ bv end if // 结束判断 if bv == 1 then // 该页面有内容? SetData(x, "Local HMI", LW, 0, 1) // X=3 → LW-0 win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1) SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗) else // 该页面无内容 SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗 end if // 结束判断 else // 权限不通过 SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗 end if // 结束判断 end macro_command // 宏结束 ``` **`btn-x4`**(X4 制丸清洗 · 权限 A/B/D) ``` macro_command main() // 宏入口:按下 X4 按钮时执行 short cls = 0 // 当前用户类别位(读 LW-9222) short x = 4 // 本按钮固定切到 X=4 short y = 0 // 运行时读回的当前 Y(1~7) short win = 0 // 计算出的目标窗口号 short ok = 0 // 权限通过标志:1=放行 short bv = 0 // 页面存在标志:1=有内容 short vpm = 0 // X4 段页面存在位图(LW-73) short pop = 1 // 弹窗置位常量 1 short bA = 0 // 类别 A 位(工程师) short bB = 0 // 类别 B 位(管理员) short bD = 0 // 类别 D 位(制丸) GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师) GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员) GETBIT(cls, bD, 3) // 取 bit3 → bD(D 制丸) if bA == 1 then // 含类别 A? ok = 1 // 权限通过 end if // 结束判断 if bB == 1 then // 含类别 B? ok = 1 // 权限通过 end if // 结束判断 if bD == 1 then // 含类别 D? ok = 1 // 权限通过 end if // 结束判断 if ok == 1 then // 权限通过 → 继续查页面 GetData(y, "Local HMI", LW, 1, 1) // 读当前 Y → y GetData(vpm, "Local HMI", LW, 73, 1) // 读 X4 段存在位图 → vpm if y == 1 then // 当前 Y=1? GETBIT(vpm, bv, 0) // 取位 0(Y1)→ bv end if // 结束判断 if y == 2 then // 当前 Y=2? GETBIT(vpm, bv, 1) // 取位 1(Y2)→ bv end if // 结束判断 if y == 3 then // 当前 Y=3? GETBIT(vpm, bv, 2) // 取位 2(Y3)→ bv end if // 结束判断 if y == 4 then // 当前 Y=4? GETBIT(vpm, bv, 3) // 取位 3(Y4)→ bv end if // 结束判断 if y == 5 then // 当前 Y=5? GETBIT(vpm, bv, 4) // 取位 4(Y5)→ bv end if // 结束判断 if y == 6 then // 当前 Y=6? GETBIT(vpm, bv, 5) // 取位 5(Y6)→ bv end if // 结束判断 if y == 7 then // 当前 Y=7? GETBIT(vpm, bv, 6) // 取位 6(Y7)→ bv end if // 结束判断 if bv == 1 then // 该页面有内容? SetData(x, "Local HMI", LW, 0, 1) // X=4 → LW-0 win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1) SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗) else // 该页面无内容 SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗 end if // 结束判断 else // 权限不通过 SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗 end if // 结束判断 end macro_command // 宏结束 ``` **`btn-y1`**(Y1 初始状态 · 权限 A/B/C/D) ``` macro_command main() // 宏入口:按下 Y1 按钮时执行 short cls = 0 // 当前用户类别位(读 LW-9222) short x = 0 // 运行时读回的当前 X(1~4) short y = 1 // 本按钮固定切到 Y=1 short win = 0 // 计算出的目标窗口号 short ok = 0 // 权限通过标志:1=放行 short bv = 0 // 页面存在标志:1=有内容 short vpm = 0 // 当前 X 段页面存在位图 short pop = 1 // 弹窗置位常量 1 short bA = 0 // 类别 A 位(工程师) short bB = 0 // 类别 B 位(管理员) short bC = 0 // 类别 C 位(上料) short bD = 0 // 类别 D 位(制丸) GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师) GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员) GETBIT(cls, bC, 2) // 取 bit2 → bC(C 上料) GETBIT(cls, bD, 3) // 取 bit3 → bD(D 制丸) if bA == 1 then // 含类别 A? ok = 1 // 权限通过 end if // 结束判断 if bB == 1 then // 含类别 B? ok = 1 // 权限通过 end if // 结束判断 if bC == 1 then // 含类别 C? ok = 1 // 权限通过 end if // 结束判断 if bD == 1 then // 含类别 D? ok = 1 // 权限通过 end if // 结束判断 if ok == 1 then // 权限通过 → 查当前 X 段位图 GetData(x, "Local HMI", LW, 0, 1) // 读当前 X → x if x == 1 then // 当前在 X1 段? GetData(vpm, "Local HMI", LW, 70, 1) // 读 X1 段位图 LW-70 end if // 结束判断 if x == 2 then // 当前在 X2 段? GetData(vpm, "Local HMI", LW, 71, 1) // 读 X2 段位图 LW-71 end if // 结束判断 if x == 3 then // 当前在 X3 段? GetData(vpm, "Local HMI", LW, 72, 1) // 读 X3 段位图 LW-72 end if // 结束判断 if x == 4 then // 当前在 X4 段? GetData(vpm, "Local HMI", LW, 73, 1) // 读 X4 段位图 LW-73 end if // 结束判断 GETBIT(vpm, bv, 0) // 取位 0(Y1)→ bv if bv == 1 then // 该页面有内容? SetData(y, "Local HMI", LW, 1, 1) // Y=1 → LW-1 win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1) SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗) else // 该页面无内容 SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗 end if // 结束判断 else // 权限不通过 SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗 end if // 结束判断 end macro_command // 宏结束 ``` **`btn-y2`**(Y2 运行 · 权限 A/B/C/D) ``` macro_command main() // 宏入口:按下 Y2 按钮时执行 short cls = 0 // 当前用户类别位(读 LW-9222) short x = 0 // 运行时读回的当前 X(1~4) short y = 2 // 本按钮固定切到 Y=2 short win = 0 // 计算出的目标窗口号 short ok = 0 // 权限通过标志:1=放行 short bv = 0 // 页面存在标志:1=有内容 short vpm = 0 // 当前 X 段页面存在位图 short pop = 1 // 弹窗置位常量 1 short bA = 0 // 类别 A 位(工程师) short bB = 0 // 类别 B 位(管理员) short bC = 0 // 类别 C 位(上料) short bD = 0 // 类别 D 位(制丸) GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师) GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员) GETBIT(cls, bC, 2) // 取 bit2 → bC(C 上料) GETBIT(cls, bD, 3) // 取 bit3 → bD(D 制丸) if bA == 1 then // 含类别 A? ok = 1 // 权限通过 end if // 结束判断 if bB == 1 then // 含类别 B? ok = 1 // 权限通过 end if // 结束判断 if bC == 1 then // 含类别 C? ok = 1 // 权限通过 end if // 结束判断 if bD == 1 then // 含类别 D? ok = 1 // 权限通过 end if // 结束判断 if ok == 1 then // 权限通过 → 查当前 X 段位图 GetData(x, "Local HMI", LW, 0, 1) // 读当前 X → x if x == 1 then // 当前在 X1 段? GetData(vpm, "Local HMI", LW, 70, 1) // 读 X1 段位图 LW-70 end if // 结束判断 if x == 2 then // 当前在 X2 段? GetData(vpm, "Local HMI", LW, 71, 1) // 读 X2 段位图 LW-71 end if // 结束判断 if x == 3 then // 当前在 X3 段? GetData(vpm, "Local HMI", LW, 72, 1) // 读 X3 段位图 LW-72 end if // 结束判断 if x == 4 then // 当前在 X4 段? GetData(vpm, "Local HMI", LW, 73, 1) // 读 X4 段位图 LW-73 end if // 结束判断 GETBIT(vpm, bv, 1) // 取位 1(Y2)→ bv if bv == 1 then // 该页面有内容? SetData(y, "Local HMI", LW, 1, 1) // Y=2 → LW-1 win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1) SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗) else // 该页面无内容 SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗 end if // 结束判断 else // 权限不通过 SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗 end if // 结束判断 end macro_command // 宏结束 ``` **`btn-y3`**(Y3 配方 · 权限 A/B/C/D) ``` macro_command main() // 宏入口:按下 Y3 按钮时执行 short cls = 0 // 当前用户类别位(读 LW-9222) short x = 0 // 运行时读回的当前 X(1~4) short y = 3 // 本按钮固定切到 Y=3 short win = 0 // 计算出的目标窗口号 short ok = 0 // 权限通过标志:1=放行 short bv = 0 // 页面存在标志:1=有内容 short vpm = 0 // 当前 X 段页面存在位图 short pop = 1 // 弹窗置位常量 1 short bA = 0 // 类别 A 位(工程师) short bB = 0 // 类别 B 位(管理员) short bC = 0 // 类别 C 位(上料) short bD = 0 // 类别 D 位(制丸) GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师) GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员) GETBIT(cls, bC, 2) // 取 bit2 → bC(C 上料) GETBIT(cls, bD, 3) // 取 bit3 → bD(D 制丸) if bA == 1 then // 含类别 A? ok = 1 // 权限通过 end if // 结束判断 if bB == 1 then // 含类别 B? ok = 1 // 权限通过 end if // 结束判断 if bC == 1 then // 含类别 C? ok = 1 // 权限通过 end if // 结束判断 if bD == 1 then // 含类别 D? ok = 1 // 权限通过 end if // 结束判断 if ok == 1 then // 权限通过 → 查当前 X 段位图 GetData(x, "Local HMI", LW, 0, 1) // 读当前 X → x if x == 1 then // 当前在 X1 段? GetData(vpm, "Local HMI", LW, 70, 1) // 读 X1 段位图 LW-70 end if // 结束判断 if x == 2 then // 当前在 X2 段? GetData(vpm, "Local HMI", LW, 71, 1) // 读 X2 段位图 LW-71 end if // 结束判断 if x == 3 then // 当前在 X3 段? GetData(vpm, "Local HMI", LW, 72, 1) // 读 X3 段位图 LW-72 end if // 结束判断 if x == 4 then // 当前在 X4 段? GetData(vpm, "Local HMI", LW, 73, 1) // 读 X4 段位图 LW-73 end if // 结束判断 GETBIT(vpm, bv, 2) // 取位 2(Y3)→ bv if bv == 1 then // 该页面有内容? SetData(y, "Local HMI", LW, 1, 1) // Y=3 → LW-1 win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1) SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗) else // 该页面无内容 SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗 end if // 结束判断 else // 权限不通过 SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗 end if // 结束判断 end macro_command // 宏结束 ``` **`btn-y4`**(Y4 设备参数 · 权限仅 A/B) ``` macro_command main() // 宏入口:按下 Y4 按钮时执行 short cls = 0 // 当前用户类别位(读 LW-9222) short x = 0 // 运行时读回的当前 X(1~4) short y = 4 // 本按钮固定切到 Y=4 short win = 0 // 计算出的目标窗口号 short ok = 0 // 权限通过标志:1=放行 short bv = 0 // 页面存在标志:1=有内容 short vpm = 0 // 当前 X 段页面存在位图 short pop = 1 // 弹窗置位常量 1 short bA = 0 // 类别 A 位(工程师) short bB = 0 // 类别 B 位(管理员) GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师) GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员) if bA == 1 then // 含类别 A? ok = 1 // 权限通过 end if // 结束判断 if bB == 1 then // 含类别 B? ok = 1 // 权限通过 end if // 结束判断 if ok == 1 then // 权限通过 → 查当前 X 段位图 GetData(x, "Local HMI", LW, 0, 1) // 读当前 X → x if x == 1 then // 当前在 X1 段? GetData(vpm, "Local HMI", LW, 70, 1) // 读 X1 段位图 LW-70 end if // 结束判断 if x == 2 then // 当前在 X2 段? GetData(vpm, "Local HMI", LW, 71, 1) // 读 X2 段位图 LW-71 end if // 结束判断 if x == 3 then // 当前在 X3 段? GetData(vpm, "Local HMI", LW, 72, 1) // 读 X3 段位图 LW-72 end if // 结束判断 if x == 4 then // 当前在 X4 段? GetData(vpm, "Local HMI", LW, 73, 1) // 读 X4 段位图 LW-73 end if // 结束判断 GETBIT(vpm, bv, 3) // 取位 3(Y4)→ bv if bv == 1 then // 该页面有内容? SetData(y, "Local HMI", LW, 1, 1) // Y=4 → LW-1 win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1) SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗) else // 该页面无内容 SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗 end if // 结束判断 else // 权限不通过 SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗 end if // 结束判断 end macro_command // 宏结束 ``` **`btn-y5`**(Y5 I/O 监控 · 权限仅 A/B) ``` macro_command main() // 宏入口:按下 Y5 按钮时执行 short cls = 0 // 当前用户类别位(读 LW-9222) short x = 0 // 运行时读回的当前 X(1~4) short y = 5 // 本按钮固定切到 Y=5 short win = 0 // 计算出的目标窗口号 short ok = 0 // 权限通过标志:1=放行 short bv = 0 // 页面存在标志:1=有内容 short vpm = 0 // 当前 X 段页面存在位图 short pop = 1 // 弹窗置位常量 1 short bA = 0 // 类别 A 位(工程师) short bB = 0 // 类别 B 位(管理员) GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师) GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员) if bA == 1 then // 含类别 A? ok = 1 // 权限通过 end if // 结束判断 if bB == 1 then // 含类别 B? ok = 1 // 权限通过 end if // 结束判断 if ok == 1 then // 权限通过 → 查当前 X 段位图 GetData(x, "Local HMI", LW, 0, 1) // 读当前 X → x if x == 1 then // 当前在 X1 段? GetData(vpm, "Local HMI", LW, 70, 1) // 读 X1 段位图 LW-70 end if // 结束判断 if x == 2 then // 当前在 X2 段? GetData(vpm, "Local HMI", LW, 71, 1) // 读 X2 段位图 LW-71 end if // 结束判断 if x == 3 then // 当前在 X3 段? GetData(vpm, "Local HMI", LW, 72, 1) // 读 X3 段位图 LW-72 end if // 结束判断 if x == 4 then // 当前在 X4 段? GetData(vpm, "Local HMI", LW, 73, 1) // 读 X4 段位图 LW-73 end if // 结束判断 GETBIT(vpm, bv, 4) // 取位 4(Y5)→ bv if bv == 1 then // 该页面有内容? SetData(y, "Local HMI", LW, 1, 1) // Y=5 → LW-1 win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1) SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗) else // 该页面无内容 SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗 end if // 结束判断 else // 权限不通过 SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗 end if // 结束判断 end macro_command // 宏结束 ``` **`btn-y6`**(Y6 报警 · 权限 A/B/C/D) ``` macro_command main() // 宏入口:按下 Y6 按钮时执行 short cls = 0 // 当前用户类别位(读 LW-9222) short x = 0 // 运行时读回的当前 X(1~4) short y = 6 // 本按钮固定切到 Y=6 short win = 0 // 计算出的目标窗口号 short ok = 0 // 权限通过标志:1=放行 short bv = 0 // 页面存在标志:1=有内容 short vpm = 0 // 当前 X 段页面存在位图 short pop = 1 // 弹窗置位常量 1 short bA = 0 // 类别 A 位(工程师) short bB = 0 // 类别 B 位(管理员) short bC = 0 // 类别 C 位(上料) short bD = 0 // 类别 D 位(制丸) GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师) GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员) GETBIT(cls, bC, 2) // 取 bit2 → bC(C 上料) GETBIT(cls, bD, 3) // 取 bit3 → bD(D 制丸) if bA == 1 then // 含类别 A? ok = 1 // 权限通过 end if // 结束判断 if bB == 1 then // 含类别 B? ok = 1 // 权限通过 end if // 结束判断 if bC == 1 then // 含类别 C? ok = 1 // 权限通过 end if // 结束判断 if bD == 1 then // 含类别 D? ok = 1 // 权限通过 end if // 结束判断 if ok == 1 then // 权限通过 → 查当前 X 段位图 GetData(x, "Local HMI", LW, 0, 1) // 读当前 X → x if x == 1 then // 当前在 X1 段? GetData(vpm, "Local HMI", LW, 70, 1) // 读 X1 段位图 LW-70 end if // 结束判断 if x == 2 then // 当前在 X2 段? GetData(vpm, "Local HMI", LW, 71, 1) // 读 X2 段位图 LW-71 end if // 结束判断 if x == 3 then // 当前在 X3 段? GetData(vpm, "Local HMI", LW, 72, 1) // 读 X3 段位图 LW-72 end if // 结束判断 if x == 4 then // 当前在 X4 段? GetData(vpm, "Local HMI", LW, 73, 1) // 读 X4 段位图 LW-73 end if // 结束判断 GETBIT(vpm, bv, 5) // 取位 5(Y6)→ bv if bv == 1 then // 该页面有内容? SetData(y, "Local HMI", LW, 1, 1) // Y=6 → LW-1 win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1) SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗) else // 该页面无内容 SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗 end if // 结束判断 else // 权限不通过 SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗 end if // 结束判断 end macro_command // 宏结束 ``` **`btn-y7`**(Y7 数据趋势 · 权限 A/B/C/D) ``` macro_command main() // 宏入口:按下 Y7 按钮时执行 short cls = 0 // 当前用户类别位(读 LW-9222) short x = 0 // 运行时读回的当前 X(1~4) short y = 7 // 本按钮固定切到 Y=7 short win = 0 // 计算出的目标窗口号 short ok = 0 // 权限通过标志:1=放行 short bv = 0 // 页面存在标志:1=有内容 short vpm = 0 // 当前 X 段页面存在位图 short pop = 1 // 弹窗置位常量 1 short bA = 0 // 类别 A 位(工程师) short bB = 0 // 类别 B 位(管理员) short bC = 0 // 类别 C 位(上料) short bD = 0 // 类别 D 位(制丸) GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师) GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员) GETBIT(cls, bC, 2) // 取 bit2 → bC(C 上料) GETBIT(cls, bD, 3) // 取 bit3 → bD(D 制丸) if bA == 1 then // 含类别 A? ok = 1 // 权限通过 end if // 结束判断 if bB == 1 then // 含类别 B? ok = 1 // 权限通过 end if // 结束判断 if bC == 1 then // 含类别 C? ok = 1 // 权限通过 end if // 结束判断 if bD == 1 then // 含类别 D? ok = 1 // 权限通过 end if // 结束判断 if ok == 1 then // 权限通过 → 查当前 X 段位图 GetData(x, "Local HMI", LW, 0, 1) // 读当前 X → x if x == 1 then // 当前在 X1 段? GetData(vpm, "Local HMI", LW, 70, 1) // 读 X1 段位图 LW-70 end if // 结束判断 if x == 2 then // 当前在 X2 段? GetData(vpm, "Local HMI", LW, 71, 1) // 读 X2 段位图 LW-71 end if // 结束判断 if x == 3 then // 当前在 X3 段? GetData(vpm, "Local HMI", LW, 72, 1) // 读 X3 段位图 LW-72 end if // 结束判断 if x == 4 then // 当前在 X4 段? GetData(vpm, "Local HMI", LW, 73, 1) // 读 X4 段位图 LW-73 end if // 结束判断 GETBIT(vpm, bv, 6) // 取位 6(Y7)→ bv if bv == 1 then // 该页面有内容? SetData(y, "Local HMI", LW, 1, 1) // Y=7 → LW-1 win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1) SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗) else // 该页面无内容 SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗 end if // 结束判断 else // 权限不通过 SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗 end if // 结束判断 end macro_command // 宏结束 ``` **`btn-login-index`**(登录:索引登入 → 按组定位;结果提示已内联,无宏编号依赖) ``` macro_command main() // 宏入口:点登录按钮时执行 short cmd = 2 // 命令=2:使用索引登入(读 LW-102 选中的账号) short res = 0 // 存放命令结果(读 LW-101) short cls = 0 // 当前用户类别位(读 LW-9222) short x = 1 // 登录后入口 X 初值 = 1 short y = 1 // 登录后入口 Y = 1 short win = 0 // 计算出的目标窗口号 short idx = 7 // 提示编号(默认 7=登录失败) short bA = 0 // 类别 A 位(工程师) short bB = 0 // 类别 B 位(管理员) short bC = 0 // 类别 C 位(上料) short bD = 0 // 类别 D 位(制丸) short z = 0 // 常量 0(清命令/清旧结果用) SetData(z, "Local HMI", LW, 101, 1) // 先清旧结果 → 防止读到上一次的码 SetData(z, "Local HMI", LW, 261, 1) // 清底部提示 → 不显示上一次的信息 SetData(z, "Local HMI", LW, 100, 1) // 命令先清 0(保证 0→2 有跳变) SetData(cmd, "Local HMI", LW, 100, 1) // 发命令 2 → LW-100(索引登入) DELAY(300) // 等 0.3 秒 GetData(res, "Local HMI", LW, 101, 1) // 读命令结果 → res(1=成功) if res == 0 then // 结果仍为 0? DELAY(300) // 再等 0.3 秒 GetData(res, "Local HMI", LW, 101, 1) // 再读一次 end if // 结束判断 if res == 1 then // 结果=1? idx = 1 // 提示编号 1:登录成功 end if // 结束判断 if res == 8 then // 结果=8? idx = 2 // 提示编号 2:账号不存在 end if // 结束判断 if res == 16 then // 结果=16? idx = 3 // 提示编号 3:密码错误 end if // 结束判断 if res == 32 then // 结果=32? idx = 4 // 提示编号 4:命令无法执行 end if // 结束判断 if res == 64 then // 结果=64? idx = 5 // 提示编号 5:名称不合法 end if // 结束判断 if res == 128 then // 结果=128? idx = 6 // 提示编号 6:密码含无效字符 end if // 结束判断 if res == 0 then // 结果=0? idx = 0 // 提示编号 0:不显示 end if // 结束判断 SetData(idx, "Local HMI", LW, 261, 1) // 提示编号 → LW-261(立即显示) if res == 1 then // 登录成功? GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师) GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员) GETBIT(cls, bC, 2) // 取 bit2 → bC(C 上料) GETBIT(cls, bD, 3) // 取 bit3 → bD(D 制丸) if bD == 1 then // 含类别 D(制丸)? x = 3 // 只有制丸组 → 入口 X3 end if // 结束判断 if bA == 1 then // 含类别 A? x = 1 // 入口 X1 end if // 结束判断 if bB == 1 then // 含类别 B? x = 1 // 入口 X1 end if // 结束判断 if bC == 1 then // 含类别 C? x = 1 // 入口 X1 end if // 结束判断 win = 101 + (x - 1) * 7 + (y - 1) // 算目标窗口号:101+(X-1)*7+(Y-1) SetData(x, "Local HMI", LW, 0, 1) // X → LW-0 SetData(y, "Local HMI", LW, 1, 1) // Y → LW-1 SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗) end if // 结束判断 end macro_command // 宏结束 ``` **`logout`**(注销并回登录页;10 号窗「打开窗口时执行」也用它) ``` macro_command main() // 宏入口:点注销按钮 / 进 10 号窗时执行 short cmd = 3 // 命令=3:注销当前账号 short win = 10 // 目标窗口号 = 10(登录页) short z = 0 // 常量 0 short z8[8] = {0,0,0,0,0,0,0,0} // 8 个 0(清用户名/密码框用) SetData(cmd, "Local HMI", LW, 100, 1) // 发命令 3 → LW-100(注销) SetData(z, "Local HMI", LW, 0, 1) // X 清 0 SetData(z, "Local HMI", LW, 1, 1) // Y 清 0 SetData(z8[0], "Local HMI", LW, 104, 8) // 清用户名框 LW-104~111(下次默认下拉登入) SetData(z8[0], "Local HMI", LW, 112, 8) // 清密码框 LW-112~119 SetData(win, "Local HMI", LW, 2, 1) // 窗口号 10 → LW-2(切回登录页) end macro_command // 宏结束 ``` **`admin-open`**(登录页 logo 上透明按钮,长按 3 秒) ``` macro_command main() // 宏入口:长按登录页隐藏按钮时执行 short on = 1 // 置位常量 1 short z8[8] = {0,0,0,0,0,0,0,0} // 8 个 0(先清输入框) SetData(z8[0], "Local HMI", LW, 104, 8) // 清用户名框 LW-104~111 SetData(z8[0], "Local HMI", LW, 112, 8) // 清密码框 LW-112~119 SetData(on, "Local HMI", LB, 125, 1) // 置 LB-125 → 弹 17 号管理员登录窗 end macro_command // 宏结束 ``` **`admin-login`**(17 号窗「登录」:固定名称登入) ``` macro_command main() // 宏入口:点 17 号窗「登录」时执行 short cmd = 1 // 命令=1:使用名称登入(读 LW-104 + LW-112) short res = 0 // 命令结果(读 LW-101) short cls = 0 // 当前用户类别位(读 LW-9222) short x = 1 // 入口 X 初值 = 1 short y = 1 // 入口 Y = 1 short win = 0 // 计算出的目标窗口号 short idx = 7 // 提示编号(默认 7=登录失败) short bA = 0 // 类别 A 位(工程师) short bB = 0 // 类别 B 位(管理员) short bC = 0 // 类别 C 位(上料) short bD = 0 // 类别 D 位(制丸) short z = 0 // 常量 0 SetData(z, "Local HMI", LW, 101, 1) // 先清旧结果 → 防止读到上一次的码 SetData(z, "Local HMI", LW, 261, 1) // 清旧提示 SetData(z, "Local HMI", LW, 100, 1) // 命令先清 0 SetData(cmd, "Local HMI", LW, 100, 1) // 发命令 1 → LW-100(名称登入) DELAY(300) // 等 0.3 秒 GetData(res, "Local HMI", LW, 101, 1) // 读命令结果 → res(1=成功) if res == 0 then // 结果仍为 0? DELAY(300) // 再等 0.3 秒 GetData(res, "Local HMI", LW, 101, 1) // 再读一次 end if // 结束判断 if res == 1 then // 结果=1? idx = 1 // 提示编号 1:登录成功 end if // 结束判断 if res == 8 then // 结果=8? idx = 2 // 提示编号 2:账号不存在 end if // 结束判断 if res == 16 then // 结果=16? idx = 3 // 提示编号 3:密码错误 end if // 结束判断 if res == 32 then // 结果=32? idx = 4 // 提示编号 4:命令无法执行 end if // 结束判断 if res == 64 then // 结果=64? idx = 5 // 提示编号 5:名称不合法 end if // 结束判断 if res == 128 then // 结果=128? idx = 6 // 提示编号 6:密码含无效字符 end if // 结束判断 if res == 0 then // 结果=0? idx = 0 // 提示编号 0:不显示 end if // 结束判断 SetData(idx, "Local HMI", LW, 261, 1) // 提示编号 → LW-261(立即显示) if res == 1 then // 登录成功? SetData(z, "Local HMI", LB, 125, 1) // 清 LB-125 → 关 17 号弹窗 GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls GETBIT(cls, bA, 0) // 取 bit0 → bA GETBIT(cls, bB, 1) // 取 bit1 → bB GETBIT(cls, bC, 2) // 取 bit2 → bC GETBIT(cls, bD, 3) // 取 bit3 → bD if bD == 1 then // 含类别 D? x = 3 // 只有制丸组 → X3 end if // 结束判断 if bA == 1 then // 含类别 A? x = 1 // 入口 X1 end if // 结束判断 if bB == 1 then // 含类别 B? x = 1 // 入口 X1 end if // 结束判断 if bC == 1 then // 含类别 C? x = 1 // 入口 X1 end if // 结束判断 win = 101 + (x - 1) * 7 + (y - 1) // 算目标窗口号 SetData(x, "Local HMI", LW, 0, 1) // X → LW-0 SetData(y, "Local HMI", LW, 1, 1) // Y → LW-1 SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗) end if // 结束判断 end macro_command // 宏结束 ``` **`admin-close`**(17 号窗「取消」) ``` macro_command main() // 宏入口:点 17 号窗「取消」时执行 short z = 0 // 常量 0 short z8[8] = {0,0,0,0,0,0,0,0} // 8 个 0 SetData(z, "Local HMI", LB, 125, 1) // 清 LB-125 → 关 17 号窗 SetData(z8[0], "Local HMI", LW, 104, 8) // 清用户名框 SetData(z8[0], "Local HMI", LW, 112, 8) // 清密码框 end macro_command // 宏结束 ``` **`close-msg`**(关闭无权限提示窗) ``` macro_command main() // 宏入口:点 11 号窗「确定」时执行 short z = 0 // 常量 0 SetData(z, "Local HMI", LB, 110, 1) // 清 LB-110 → 关闭 11 号无权限窗 end macro_command // 宏结束 ``` **`close-nopage`**(关闭 16 号「无内容」提示窗) ``` macro_command main() // 宏入口:点 16 号窗「确定」时执行 short z = 0 // 常量 0 SetData(z, "Local HMI", LB, 124, 1) // 清 LB-124 → 关闭 16 号无内容窗 end macro_command // 宏结束 ``` **用户管理 `usr-*`** | 宏 | 命令 | 说明 | | --- | --- | --- | | `usr-init` | — | 14 号窗「打开窗口时执行」:清 `LW-104`/`LW-112`/`LW-103`/`LW-101`,清 `LB-121` | | `user-open` | — | 顶部按钮:仅 B/admin → 置 `LB-122` | | `usr-back` | — | 清 `LB-122` | | `usr-add` | `5` | 新增(`LW-104`+`LW-112`+`LW-103`) | | `usr-delete` | — | 置 `LB-121` 弹确认 | | `usr-delete-ok` | `8` | 按索引删除 | | `usr-delete-cancel` | — | 清 `LB-121` | | `usr-getlevel` | `14` | 按索引读权限 → `LW-103` | | `usr-setlevel` | `10` | 按索引设权限 | | `usr-setpwd` | `12` | 按索引设密码 | ``` macro_command main() // 宏入口:用户管理按钮(以 cmd=14 读取权限为例) short cmd = 14 // 命令值:改成 5/8/10/12 等即为对应功能 SetData(cmd, "Local HMI", LW, 100, 1) // 发命令 → LW-100 end macro_command // 宏结束 ``` > 其余 `usr-*` 同上模板:`cmd` = 5 / 8 / 10 / 12;`user-open` 置 / `usr-back` 清 `LB-122`,`usr-delete` / `usr-delete-cancel` 置 / 清 `LB-121`,`usr-init` 清输入。 **关于窗 `about-*`**:`about-open` 置 `LB-123`(弹 13 号窗);`about-close` 清 `LB-123`。 **修改时间** | 宏 | 触发 | 作用 | | --- | --- | --- | | `open-time` | 时钟上透明按钮(仅 B) | 读 `LW-9017`~`9022` → `LW-40`~`45`,置 `LB-120` | | `set-time` | 12 号窗「设定」 | `LW-40`~`45` → `LW-9017`~`9022`(设置 RTC),清 `LB-120` | | `close-time` | 12 号窗「取消」 | 清 `LB-120` | ``` macro_command main() // 宏入口:改时间弹窗点「设定」时执行 short v[6] = {0,0,0,0,0,0} // 暂存数组:秒/分/时/日/月/年 short z = 0 // 常量 0 GetData(v[0], "Local HMI", LW, 40, 6) // 从 LW-40~45 读入 6 个值 → v SetData(v[0], "Local HMI", LW, 9017, 6) // v 写入 RTC 寄存器 LW-9017~9022(设置时间) SetData(z, "Local HMI", LB, 120, 1) // 清 LB-120 → 关闭 12 号弹窗 end macro_command // 宏结束 ``` **网络设置 `net-*`** **`net-read`**(13 号窗「打开窗口时执行」:系统值 → 暂存 RW) ``` macro_command main() // 宏入口:进 13 号窗时执行 short v[4] = {0,0,0,0} // 4 字暂存数组 short line = 1 // 制丸线别(1=A / 2=B) GetData(line, "Local HMI", RW, 61, 1) // 读 RW-61 线别 GetData(v[0], "Local HMI", LW, 9129, 4) // 读 HMI IP SetData(v[0], "Local HMI", RW, 20, 4) // → RW-20~23 GetData(v[0], "Local HMI", LW, 10750, 4) // 读 HMI 掩码 SetData(v[0], "Local HMI", RW, 24, 4) // → RW-24~27 GetData(v[0], "Local HMI", LW, 9125, 4) // 读 HMI 网关 SetData(v[0], "Local HMI", RW, 28, 4) // → RW-28~31 GetData(v[0], "Local HMI", LW, 9600, 4) // 读上料 PLC(设备4)IP SetData(v[0], "Local HMI", RW, 40, 4) // → RW-40~43 GetData(v[0], "Local HMI", LW, 9605, 4) // 读制丸 PLC(设备5)IP if line == 1 then // 当前选 A 线? SetData(v[0], "Local HMI", RW, 44, 4) // → RW-44~47(制丸A) else // 当前选 B 线 SetData(v[0], "Local HMI", RW, 48, 4) // → RW-48~51(制丸B) end if // 结束判断 end macro_command // 宏结束 ``` **`net-apply`**(工程宏 ID 037;13 号窗「应用」按钮 + 宏属性勾「当 HMI 启动时即执行一次」) > **设备归属(10-27 按 EB 设备列表实测,数字以此为准)** > `设备4 = 制丸1(192.168.189.22)`、`设备5 = 上料清洗(192.168.189.2)`,两台都是 S7CommPlus + 符号寻址。 > 所以:**上料 IP → `LW-9605` / `LB-10071`(设备5)**,**制丸 IP → `LW-9600` / `LB-10070`(设备4)**。 ``` macro_command main() // 宏入口:点「应用」/ 开机自动套用 short v[4] = {0,0,0,0} // 4 字暂存数组 short hmi0 = 0 // HMI IP 第一段(判断是否配置过) short role = 0 // 本机角色(1上料/2制丸A/3制丸B) short line = 1 // 制丸线别(1=A/2=B) short okp = 0 // 是否连接制丸设备:1=连 short on = 1 // 置位常量 short z = 0 // 常量 0 GetData(hmi0, "Local HMI", RW, 20, 1) // 读 RW-20(HMI IP 第一段) GetData(role, "Local HMI", RW, 60, 1) // 读 RW-60(本机角色) GetData(line, "Local HMI", RW, 61, 1) // 读 RW-61(线别) if line == 0 then // 线别未设置? line = 1 // 默认 A 线 end if // 结束判断 if role == 1 then // 上料屏? okp = 1 // 连制丸设备(线别按 RW-61) end if // 结束判断 if role == 2 then // 制丸A屏? line = 1 // 强制 A 线 okp = 1 // 连制丸设备 end if // 结束判断 if role == 3 then // 制丸B屏? line = 2 // 强制 B 线 okp = 1 // 连制丸设备 end if // 结束判断 SetData(line, "Local HMI", RW, 61, 1) // 回写线别(界面显示一致) if hmi0 == 0 then // HMI IP 没填 → 跳过 HMI 部分 hmi0 = 0 // (保持原 HMI 网络) else // 已填 → 应用 HMI 网络 GetData(v[0], "Local HMI", RW, 20, 4) // RW → HMI IP SetData(v[0], "Local HMI", LW, 9129, 4) // 写 LW-9129~9132 GetData(v[0], "Local HMI", RW, 24, 4) // RW → HMI 掩码 SetData(v[0], "Local HMI", LW, 10750, 4) // 写 LW-10750~10753 GetData(v[0], "Local HMI", RW, 28, 4) // RW → HMI 网关 SetData(v[0], "Local HMI", LW, 9125, 4) // 写 LW-9125~9128 SetData(on, "Local HMI", LB, 12094, 1) // 置 LB-12094 → HMI 网络生效 end if // 结束判断 GetData(v[0], "Local HMI", RW, 40, 4) // RW → 上料 PLC IP if v[0] == 0 then // 没填(新屏/模拟)→ 不写、不重连 v[0] = 0 // 保留工程里的设备 IP else // 已填 → 套用(设备5 = 上料清洗) SetData(v[0], "Local HMI", LW, 9605, 4) // 写设备5 IP SetData(on, "Local HMI", LB, 10071, 1) // 重连设备5 end if // 结束判断 if okp == 1 then // 需要连制丸设备? if line == 1 then // 选 A 线 GetData(v[0], "Local HMI", RW, 44, 4) // RW → 制丸A IP else // 选 B 线 GetData(v[0], "Local HMI", RW, 48, 4) // RW → 制丸B IP end if // 结束判断 if v[0] == 0 then // 没填 → 不写、不重连 v[0] = 0 // 保留工程里的设备 IP else // 已填 → 套用(设备4 = 制丸1) SetData(v[0], "Local HMI", LW, 9600, 4) // 写设备4 IP SetData(on, "Local HMI", LB, 10070, 1) // 重连设备4 end if // 结束判断 end if // 结束判断(角色=0:不连制丸设备,防误连) DELAY(1000) // 等 1 秒(嫌开机慢可改 300) SetData(z, "Local HMI", LB, 12094, 1) // 清 LB-12094 SetData(z, "Local HMI", LB, 10070, 1) // 清 LB-10070 SetData(z, "Local HMI", LB, 10071, 1) // 清 LB-10071 end macro_command // 宏结束 ``` **与工程现版(10-27 摘录)的三个差别** | # | 现版 | 本节 | | --- | --- | --- | | 1 | 注释把设备号写反(`写上料 PLC(设备4)`) | 注释已改正;**数字一个没改** | | 2 | 无 `v[0]==0` 保护,RW 为空时把 IP 刷成 `0.0.0.0` | 首段为 0 跳过写入与重连 | | 3 | `DELAY(1000)` | 保留,可改 300 缩短开机等待 | > `LB-11963`/`LB-11964` 那条屏蔽设备 1~8 通讯弹窗的宏(ID 048 `屏蔽通讯异常提示`,周期执行)与本宏无关,别混。 **`line-ab-switch`**(13 号窗「A/B 切换」按钮;仅本机角色=1 生效) ``` macro_command main() // 宏入口:点 A/B 线切换按钮 short v[4] = {0,0,0,0} // 4 字暂存数组 short role = 0 // 本机角色(读 RW-60) short line = 1 // 当前线别 short on = 1 // 置位常量 short z = 0 // 常量 0 GetData(role, "Local HMI", RW, 60, 1) // 读本机角色 if role == 1 then // 只有上料屏允许切换 GetData(line, "Local HMI", RW, 61, 1) // 读当前线别 if line == 1 then // 当前 A → 切 B line = 2 // 目标 B else // 当前 B → 切 A line = 1 // 目标 A end if // 结束判断 SetData(line, "Local HMI", RW, 61, 1) // 写回 RW-61 if line == 1 then // 目标 A 线 GetData(v[0], "Local HMI", RW, 44, 4) // 取制丸A IP else // 目标 B 线 GetData(v[0], "Local HMI", RW, 48, 4) // 取制丸B IP end if // 结束判断 SetData(v[0], "Local HMI", LW, 9605, 4) // 写设备5 IP SetData(on, "Local HMI", LB, 10071, 1) // 重连设备5 DELAY(1000) // 等 1 秒 SetData(z, "Local HMI", LB, 10071, 1) // 清重连位 end if // 非上料屏:无动作(线别锁定) end macro_command // 宏结束 ``` ### X2Y2 分区聚焦弹窗(工程实际名 `x2y2-focus-area*`) > 施工见 `开发主文件.md` 7.7.3。**旧文档的 `area-1~4` / `area-close` 作废**,工程实际是: | 宏 | 触发 | 作用 | | --- | --- | --- | | `x2y2-focus-area1` | 区域①透明键 | 写 `LW-50` = 目标窗口号 | | `x2y2-focus-area2` | 区域②透明键 | 同上 | | `x2y2-focus-area3` | 区域③透明键 | 同上 | | `x2y2-focus-area-close` | 「关闭」键 / X2Y2 打开窗口时 | `LW-50` = 0 收起 | **只有 3 个区域**(原第④区已并入③),没有 area-4。 **窗口号已确认**:工程窗口表里 `30/31/32 = x2y2-focus-area1/2/3`,所以 `LW-50` 写的是 **30/31/32**;旧版本节写的 `141/142/143` 作废(`地址表.md` 5.1 已同步)。 --- ## 6.2 补录:2026-10-27 从工程逐个截图核对的宏 > 以下正文与 EB 宏编辑器里的实际内容一致(编号/名称取自宏列表)。执行条件:无标记=按钮触发;`P`=周期执行。 **`x2y2-focus-area1`(ID 039)** ``` macro_command main() // 宏入口:点该区域时执行 short win = 30 // 目标弹窗窗口号 SetData(win, "Local HMI", LW, 50, 1) // 写 LW-50 → 间接窗口显示 30 end macro_command // 宏结束 ``` **`x2y2-focus-area2`(ID 040)**:同上,`win = 31`(显示 31) **`x2y2-focus-area3`(ID 041)**:同上,`win = 32`(显示 32) ``` macro_command main() // 宏入口:关闭区域弹窗 short z = 0 // 常量 0 SetData(z, "Local HMI", LW, 50, 1) // 写 LW-50=0 → 间接窗口收起 end macro_command // 宏结束 ``` (`x2y2-focus-area-close`,ID 043) **`IO切换上料`(ID 042)/ `IO切换清洗`(ID 044)/ `IO切换制丸`(ID 045)** 三支结构相同,只有两个常量不同: ``` macro_command main() unsigned char byteA, byteB byteA = 9 // → LW-300:IO 组索引(供 050 IO 判断) byteB = 158 // → LW-2:目标窗口号 SetData(byteA, "Local HMI", LW, 300, 1) SetData(byteB, "Local HMI", LW, 2, 1) end macro_command ``` | 宏 | `byteA`(LW-300) | `byteB`(LW-2 → 窗口) | 对应窗口 | | --- | --- | --- | --- | | `IO切换上料` | 9 | 158 | 158 = 上料-IO监控DI1-2 | | `IO切换清洗` | 15 | 168 | 168 = 清洗-IO监控DO11-12 | | `IO切换制丸` | 1 | 151 | 151 = 制丸-IO监控DI1-2 | **`上料参数`(ID 046)** ``` macro_command main() unsigned char byteB byteB = 210 // 目标窗口号 SetData(byteB, "Local HMI", LW, 2, 1) end macro_command ``` > ⚠ **存疑**:窗口 210 在工程窗口表里是「清洗-点动」,不是上料参数页。要么宏值过时,要么窗口被改作他用,需现场确认。 **`温度监控`(ID 047,周期 10×100ms = 1 s)** ``` macro_command main() float temp[16] // 16 个 REAL,每个占 2 个 LW GetData(temp[0], "制丸1", "PLC.Blocks.HMI_EM02.Temperature_PV[1]", 0, 16) SetData(temp[0], "Local HMI", LW, 200, 16) end macro_command ``` > ⚠ **长度存疑**:`float` 每个占 2 个寄存器,16 个 REAL = 32 字(LW200~231)。但 `SetData(..., LW, 200, 16)` 只写 16 字 = 8 个 REAL。注释写的 `[16]→LW230/231` 与调用参数**必有一处错**,需核对显示元件的地址范围。 **`出条温度监控`(ID 049,周期 10×100ms = 1 s)** ``` macro_command main() float temp[10] GetData(temp[0], "制丸1", "PLC.Blocks.HMI_EM02.HIKMICRO_Temp_R[1]", 0, 10) SetData(temp[0], "Local HMI", LW, 240, 10) end macro_command ``` > ⚠ 同上:10 个 REAL = 20 字(LW240~259),`count=10` 只覆盖到 LW249。 **`屏蔽通讯异常提示`(ID 048,周期 1×100ms = 100 ms)** ``` macro_command main() short ON ON = 1 SetData(ON, "Local HMI", LB, 11960, 1) SetData(ON, "Local HMI", LB, 11961, 1) SetData(ON, "Local HMI", LB, 11962, 1) SetData(ON, "Local HMI", LB, 11963, 1) SetData(ON, "Local HMI", LB, 11964, 1) SetData(ON, "Local HMI", LB, 11965, 1) SetData(ON, "Local HMI", LB, 11966, 1) SetData(ON, "Local HMI", LB, 11967, 1) end macro_command ``` > 含义:每 100 ms 把**设备 1~8** 的 "Device No Response" 弹窗全部压回屏蔽。要恢复提示必须改这支宏。周期可放宽到 1 s,没必要 100 ms。 **`IO`(ID 050,周期 1×100ms = 100 ms)** 按 `LW-300` 的索引读对应 IO 组到四个字节,并写 `LW-310~313` 供画面调试显示。 ``` macro_command main() short bTrigger unsigned char byteA, byteB, byteC, byteD bTrigger = 0 byteA = 0 byteB = 0 byteC = 0 byteD = 0 GetData (bTrigger, "Local HMI", LW, 300, 1) // IO 组索引(042/044/045 写入) if bTrigger==1 then // 制丸 DI01-02 → 窗口 151 GetData (byteA, "制丸1", "PLC.Tags.Table.Local_DI01A", 1) GetData (byteB, "制丸1", "PLC.Tags.Table.Local_DI01B", 1) GetData (byteC, "制丸1", "PLC.Tags.Table.Local_DI02A", 1) GetData (byteD, "制丸1", "PLC.Tags.Table.Local_DI02B", 1) end if if bTrigger==2 then // 制丸 DI03-04 → 152 GetData (byteA, "制丸1", "PLC.Tags.Table.Local_DI03A", 1) GetData (byteB, "制丸1", "PLC.Tags.Table.Local_DI03B", 1) GetData (byteC, "制丸1", "PLC.Tags.Table.Local_DI04A", 1) GetData (byteD, "制丸1", "PLC.Tags.Table.Local_DI04B", 1) end if if bTrigger==3 then // 制丸 DI05 → 153 GetData (byteA, "制丸1", "PLC.Tags.Table.Local_DI05A", 1) GetData (byteB, "制丸1", "PLC.Tags.Table.Local_DI05B", 1) end if if bTrigger==4 then // 制丸 DO01-02 → 154 GetData (byteA, "制丸1", "PLC.Tags.Table.Local_DO01A", 1) GetData (byteB, "制丸1", "PLC.Tags.Table.Local_DO01B", 1) GetData (byteC, "制丸1", "PLC.Tags.Table.Local_DO02A", 1) GetData (byteD, "制丸1", "PLC.Tags.Table.Local_DO02B", 1) end if if bTrigger==5 then // 制丸 DO03-04 → 155 GetData (byteA, "制丸1", "PLC.Tags.Table.Local_DO03A", 1) GetData (byteB, "制丸1", "PLC.Tags.Table.Local_DO03B", 1) GetData (byteC, "制丸1", "PLC.Tags.Table.Local_DO04A", 1) GetData (byteD, "制丸1", "PLC.Tags.Table.Local_DO04B", 1) end if // 6、7 未使用(跳过) if bTrigger==8 then // 上料 DI01-02 → 158 GetData (byteA, "上料清洗", "PLC.Tags.Table.Local_DI01A", 1) GetData (byteB, "上料清洗", "PLC.Tags.Table.Local_DI01B", 1) GetData (byteC, "上料清洗", "PLC.Tags.Table.Local_DI02A", 1) GetData (byteD, "上料清洗", "PLC.Tags.Table.Local_DI02B", 1) end if if bTrigger==9 then // 上料 DI03-04 → 159 GetData (byteA, "上料清洗", "PLC.Tags.Table.Local_DI03A", 1) GetData (byteB, "上料清洗", "PLC.Tags.Table.Local_DI03B", 1) GetData (byteC, "上料清洗", "PLC.Tags.Table.Local_DI04A", 1) GetData (byteD, "上料清洗", "PLC.Tags.Table.Local_DI04B", 1) end if if bTrigger==10 then // 上料 DI05-06 → 160 GetData (byteA, "上料清洗", "PLC.Tags.Table.Local_DI05A", 1) GetData (byteB, "上料清洗", "PLC.Tags.Table.Local_DI05B", 1) GetData (byteC, "上料清洗", "PLC.Tags.Table.Local_DI06A", 1) GetData (byteD, "上料清洗", "PLC.Tags.Table.Local_DI06B", 1) end if if bTrigger==11 then // 上料 DI07 + Remote DI21 → 161 GetData (byteA, "上料清洗", "PLC.Tags.Table.Local_DI07A", 1) GetData (byteB, "上料清洗", "PLC.Tags.Table.Local_DI07B", 1) GetData (byteC, "上料清洗", "PLC.Tags.Table.Remote_DI21A", 1) GetData (byteD, "上料清洗", "PLC.Tags.Table.Remote_DI21B", 1) end if if bTrigger==12 then // 上料 DO01-02 → 162 GetData (byteA, "上料清洗", "PLC.Tags.Table.Local_DO01A", 1) GetData (byteB, "上料清洗", "PLC.Tags.Table.Local_DO01B", 1) GetData (byteC, "上料清洗", "PLC.Tags.Table.Local_DO02A", 1) GetData (byteD, "上料清洗", "PLC.Tags.Table.Local_DO02B", 1) end if if bTrigger==13 then // 上料 DO03-04 → 163 GetData (byteA, "上料清洗", "PLC.Tags.Table.Local_DO03A", 1) GetData (byteB, "上料清洗", "PLC.Tags.Table.Local_DO03B", 1) GetData (byteC, "上料清洗", "PLC.Tags.Table.Local_DO04A", 1) GetData (byteD, "上料清洗", "PLC.Tags.Table.Local_DO04B", 1) end if if bTrigger==14 then // 上料 DO05-06 → 164 GetData (byteA, "上料清洗", "PLC.Tags.Table.Local_DO05A", 1) GetData (byteB, "上料清洗", "PLC.Tags.Table.Local_DO05B", 1) GetData (byteC, "上料清洗", "PLC.Tags.Table.Local_DO06A", 1) GetData (byteD, "上料清洗", "PLC.Tags.Table.Local_DO06B", 1) end if if bTrigger==15 then // 清洗 DI11-12 → 166 GetData (byteA, "上料清洗", "PLC.Tags.Table.Local_DI11A", 1) GetData (byteB, "上料清洗", "PLC.Tags.Table.Local_DI11B", 1) GetData (byteC, "上料清洗", "PLC.Tags.Table.Local_DI12A", 1) GetData (byteD, "上料清洗", "PLC.Tags.Table.Local_DI12B", 1) end if if bTrigger==16 then // 清洗 DI13-14 → 167 GetData (byteA, "上料清洗", "PLC.Tags.Table.Local_DI13A", 1) GetData (byteB, "上料清洗", "PLC.Tags.Table.Local_DI13B", 1) GetData (byteC, "上料清洗", "PLC.Tags.Table.Local_DI14A", 1) GetData (byteD, "上料清洗", "PLC.Tags.Table.Local_DI14B", 1) end if if bTrigger==17 then // 清洗 DO11-12 → 168 GetData (byteA, "上料清洗", "PLC.Tags.Table.Local_DO11A", 1) GetData (byteB, "上料清洗", "PLC.Tags.Table.Local_DO11B", 1) GetData (byteC, "上料清洗", "PLC.Tags.Table.Local_DO12A", 1) GetData (byteD, "上料清洗", "PLC.Tags.Table.Local_DO12B", 1) end if if bTrigger==18 then // 清洗 DO13-14 → 169 GetData (byteA, "上料清洗", "PLC.Tags.Table.Local_DO13A", 1) GetData (byteB, "上料清洗", "PLC.Tags.Table.Local_DO13B", 1) GetData (byteC, "上料清洗", "PLC.Tags.Table.Local_DO14A", 1) GetData (byteD, "上料清洗", "PLC.Tags.Table.Local_DO14B", 1) end if if bTrigger==19 then // Remote DO21 GetData (byteA, "上料清洗", "PLC.Tags.Table.Remote_DO21A", 1) GetData (byteB, "上料清洗", "PLC.Tags.Table.Remote_DO21B", 1) end if // 20~24 为制丸2 预留,现被注释掉 // ===== 调试监控输出:画面加 LW-310~313 数值元件查看 ===== SetData(byteA, "Local HMI", LW, 310, 1) SetData(byteB, "Local HMI", LW, 311, 1) SetData(byteC, "Local HMI", LW, 312, 1) SetData(byteD, "Local HMI", LW, 313, 1) end macro_command ``` > `bTrigger` 6、7 **缺号未用**;`20~24` 是「制丸2」的预留分支,已注释。 > 索引 ↔ 窗口对照:1~5 → 151~155;8~14 → 158~164;15~18 → 166~169;19 → Remote DO21。 ### 6.2.1 补录时发现的问题 | # | 问题 | 影响 | | --- | --- | --- | | 1 | **`LW-300` 被两处占用**:`X1Y1` 文档里是「节点状态」首地址;现在 042/044/045 写它、050 读它 | 若 X1Y1 仍用 `LW-300~311`,节点状态会被 IO 索引覆盖 | | 2 | `上料参数` 写 `LW-2 = 210`,而 210 是「清洗-点动」 | 点“上料参数”会跳到清洗点动页 | | 3 | 047/049 的 float 拷贝长度与注释不符 | 显示可能只更新一半点位 | | 4 | 048 周期 100 ms 写 8 个位 | 无谓负载,建议 1 s | | 5 | 050 周期 100 ms 读 4×N 个符号 | IO 页不看时也在刷,建议改成按页面触发 | | 6 | **`IO切换上料` 索引 9 却跳窗口 158**(158 是 DI1-2,索引 9 读 DI3-4) | 该页显示的是上一组 IO,值对不上标题 | | 7 | **`IO切换清洗` 索引 15 却跳窗口 168**(15=DI11-12,168=DO11-12) | 同上,错 2 组 | | 8 | `050` 末尾写 `LW-310~313` 调试值,与旧文档 X1Y1 的 `LW-300~311` 节点状态重叠 | `LW-300` 区已被 IO 占用,X1Y1 地址需重新确认 | | 9 | `bTrigger` 6、7 缺号;20~24 是制丸2 预留(已注释) | 索引不连续,日后加页容易再次错位 |