LAD 梯形图完全参考手册
梯形图 (Ladder Diagram, LAD) 是 IEC 61131-3 标准定义的 PLC 编程语言之一,也是工业自动化领域最经典、最直观的编程方式。Darra IDE 提供完整的 LAD 编辑器,支持从简单开关逻辑到复杂功能块调用的全范围编程。
本文是一站式 LAD 参考手册,按照 "菜鸟教程"风格编排,涵盖所有元件、参数、示例和最佳实践。如需编辑操作指南,请参阅 LAD 编辑器;如需调试方法,请参阅 LAD 调试。
目录
- LAD 梯形图入门
- 触点 (Contacts)
- 线圈 (Coils)
- 定时器 (Timers)
- 计数器 (Counters)
- 比较指令 (Comparison)
- 数学运算 (Math)
- 移动指令 (Move)
- 转换指令 (Convert)
- 程序控制 (Program Control)
- 位逻辑指令 (Bit Logic)
- 位移指令 (Shift)
- 功能块调用 (FB/FC Call)
- 实际应用示例
- 调试与监视
- 附录:元件速查表
1. LAD 梯形图入门
1.1 什么是梯形图?
梯形图直接继承自继电器控制电路 (Relay Ladder Logic, RLL)。在继电器系统中,控制逻辑通过硬件接线实现:按钮、继电器触点、线圈之间用导线连接。梯形图将这些硬件元件映射为软件符号,在 PLC 内部通过扫描执行代替物理接线。
继电器电路: 梯形图等价:
电源+ ────按钮────继电器──── 电源- 左母线 按钮 线圈 右母线
常开触点 │ ──┬──┤[ ]──────────( )────┬──
│ │ │ │
└──── 指示灯 ────┘ └─────── 能流方向 ──────┘
对于有电气背景的工程师,梯形图几乎不需要额外学习即可读懂。这也是梯形图几十年来长盛不衰的根本原因。
1.2 基本概念
梯级 (Rung)
梯形图程序由多个梯级组成,每个梯级从左母线到右母线形成一个完整电路。PLC 按梯级顺序从上到下执行:
┌─────────────────────────────────────┐
梯级 1 │──┤ ├──┤ ├──┤/├──────────( )──────│
├─────────────────────────────────────┤
梯级 2 │──┤ ├──┤ TON ─────┤ ├──────(S)────│
├─────────────────────────────────────┤
梯级 3 │──┤/├──────────────────────(R)────│
└─────────────────────────────────────┘
能流 (Power Flow)
能流是理解梯形图的核心概念:能流从左母线出发,经过各串联/并联的触点,到达右端的线圈。只有当触点链全部导通时,线圈才"通电"。
- 能流存在 → 线圈置 TRUE
- 能流中断 → 线圈置 FALSE
- 触点串联 = 逻辑 AND
- 触点并联 = 逻辑 OR
串联 (AND): 并联 (OR):
──┤ ├──┤ ├── ──┤ ├────
│
├──┤ ├──
│
└──┤ ├──
扫描周期
梯形图程序在每个 PLC 扫描周期中按从左到右、从上到下的顺序执行:
扫描周期:
┌────────────────────────────────────────────────────┐
│ 读输入 → 执行梯级 1 → 梯级 2 → ... → 写输出 │
└────────────────────────────────────────────────────┘
↑ LAD 执行在此阶段完成
- 读取输入 — 采样物理输入到过程映像区 (PII)
- 执行梯级 — 按梯级顺序逐级执行,每级内部从左到右
- 更新输出 — 将结果写入物理输出 (PIQ)
1.3 梯形图 vs SCL
| 维度 | 梯形图 (LAD) | SCL (结构化控制语言) |
|---|---|---|
| 表现形式 | 图形化、接线图 | 文本、类 Pascal 语法 |
| 学习曲线 | 低(电气工程师直觉) | 中等(需编程基础) |
| 开关逻辑 | 非常直观 | 需转换为布尔表达式 |
| 数学运算 | 调用功能块实现 | 直接写表达式 |
| 复杂算法 | 不擅长(梯级会膨胀) | 擅长(循环/数组/条件分支) |
| 在线调试 | 导通着色直观 | 变量监视 |
| 代码复用 | 通过 FB 调用 | 函数/功能块/库 |
选型建议
| 场景 | 推荐语言 |
|---|---|
| 简单的启停、联锁、安全回路 | LAD |
| 顺序控制(工步切换) | LAD + SCL 动作框 |
| 电机正反转、阀门控制 | LAD |
| PID 调节、温度控制 | SCL(或调用 FB) |
| 数据处理、数组操作 | SCL |
| 通讯解析、协议组包 | SCL |
| 报警逻辑、状态指示 | LAD |
| 复杂状态机 | SCL |
| 高速计数、编码器处理 | LAD(调用高速计数器 FB) |
1.4 IDE 编辑器速览
Darra IDE 的 LAD 编辑器提供以下核心能力:
┌───────────────────────────────────────────────────────┐
│ 工具箱 编辑区 属性面板 │
│ ┌───────┐ ┌───────────────────────────────┐ ┌──────┐ │
│ │触点 │ │ // 电机启动控制 │ │变量 │ │
│ │ ├── │ │ bStart bStop bMotor │ │ 名称 │ │
│ │ ├/├ │ │──┤ ├────┤/├────┬──────( )── │ │ 类型 │ │
│ │线圈 │ │ │ │ │ 注释 │ │
│ │ ( ) │ │ bMotor│ │ │ │ │
│ │ (S) │ │────┤ ├────────┘ │ │ │ │
│ │定时器 │ │ │ │ │ │
│ │ TON │ │ [状态: 在线 | 扫描 10ms] │ │ │ │
│ └───────┘ └───────────────────────────────┘ └──────┘ │
└───────────────────────────────────────────────────────┘
- 完整的 IEC 61131-3 LAD 支持:常开/常闭触点、标准/置位/复位线圈、正/负跳变检测
- 内置功能块调用:TON/TOF/TP 定时器、CTU/CTD/CTUD 计数器、比较与数学运算块
- 自定义 FB/FC 调用:在 LAD 中调用 SCL 编写的功能块,端口自动展开
- 分支与并联:多路并联、梯级折返、嵌套分支
- 在线监视:导通着色(绿色=通/灰色=断)、强制值高亮、变量悬浮显示
- 与 SCL 混合编程:同一 POU 内部分梯级用 LAD、部分用 SCL 动作框
- 一键切换视图:POU 整体切换为 SCL 等价代码查看
- 撤销/重做:支持多级撤销(默认 50 步)
2. 触点 (Contacts)
触点是梯形图中用于读取布尔变量状态的元件。触点不改变变量值,只根据变量状态决定是否允许能流通过。
2.1 常开触点 (NO Contact)
符号:
变量名
──┤ ├──
ASCII 表示:---| |---
参数:
| 属性 | 说明 |
|---|---|
| 符号 | --[ ]-- 或 --┤ ├── |
| 变量类型 | BOOL |
| 能流条件 | 变量为 TRUE 时导通 |
| SCL 等价 | IF <变量> THEN |
| 典型用途 | 读取传感器、按钮、状态位 |
示例:
bSensor1 bOutput
──┤ ├──────────────────────( )──
// bSensor1 = TRUE 时 bOutput 导通
// SCL: bOutput := bSensor1;
技巧:
- 常开触点是梯形图最常用的元件,对应物理电路中的"常开按钮"——按下导通
- 串联多个常开触点 = AND 逻辑
- 并联多个常开触点 = OR 逻辑
2.2 常闭触点 (NC Contact)
符号:
变量名
──┤/├──
ASCII 表示:---|/|---
参数:
| 属性 | 说明 |
|---|---|
| 符号 | --[/]-- 或 --┤/├── |
| 变量类型 | BOOL |
| 能流条件 | 变量为 FALSE 时导通 |
| SCL 等价 | IF NOT <变量> THEN |
| 典型用途 | 急停(断线即停)、限位开关常闭 |
示例:
bEStop bRunEnable
──┤/├──────────────────────( )──
// 急停未按下 (bEStop = FALSE) 时运行允许
// SCL: bRunEnable := NOT bEStop;
技巧:
- 常闭触点对应物理电路中的"常闭按钮"——按下断开
- 急停按钮必须用常闭触点:断线时 FALSE → 触点导通 → 触发保护;如果断线时用常开,系统会认为"急停未按下"而继续运行,非常危险
- 安全回路中所有安全信号(急停、安全门、光栅)都使用常闭触点串联
2.3 上升沿检测 (P-Trigger)
符号:
变量名
──┤P ├──
ASCII 表示:---|P|---
参数:
| 属性 | 说明 |
|---|---|
| 符号 | --[P]-- 或 --┤P ├── |
| 变量类型 | BOOL |
| 能流条件 | 变量从 FALSE → TRUE 时导通一个扫描周期 |
| SCL 等价 | R_TRIG(CLK := <变量>).Q |
| 典型用途 | 按钮按下触发、启动信号、计数脉冲 |
时序图:
变量 ──┐ ┌──── ┌────
│ │ │
└────────┘────────────┘────────
能流 ──┐ ┌────┐ ┌──── ──┐ ┌────
│ │ │ │ │ │
└──┘ └──┘──────────┘──┘
↑导通1周期 ↑导通1周期
示例:
bButton bTriggered
──┤P ├──────────────────────( )──
// 每次按钮按下 (FALSE→TRUE),bTriggered 导通一个扫描周期
// SCL: R_TRIG(CLK := bButton).Q → bTriggered
技巧:
- 上升沿检测不会在 TRUE 持续期间一直导通,只导通一个扫描周期
- 适合做"只执行一次"的动作:如触发计数器、设置标志位
- 内部隐式使用 R_TRIG 功能块实现
2.4 下降沿检测 (N-Trigger)
符号:
变量名
──┤N ├──
ASCII 表示:---|N|---
参数:
| 属性 | 说明 |
|---|---|
| 符号 | --[N]-- 或 --┤N ├── |
| 变量类型 | BOOL |
| 能流条件 | 变量从 TRUE → FALSE 时导通一个扫描周期 |
| SCL 等价 | F_TRIG(CLK := <变量>).Q |
| 典型用途 | 停止检测、故障恢复、完成信号 |
时序图:
变量 ┌──── ┌────
│ │
└────────────┘────────────
能流 ┌──┐ ┌──┐
│ │ │ │
└──┘───────┘──┘
↑导通1周期 ↑导通1周期
示例:
bFaultClear bResetDetected
──┤N ├──────────────────────( )──
// 故障清除信号下降沿时导通一个周期
// SCL: F_TRIG(CLK := bFaultClear).Q → bResetDetected
技巧:
- 与上升沿互补,检测信号的释放时刻
- 常用于故障恢复检测:当故障信号从 TRUE 变为 FALSE 时触发恢复流程
2.5 取反 (NOT)
符号:
──┤NOT├──
参数:
| 属性 | 说明 |
|---|---|
| 符号 | --[NOT]-- 或 --┤NOT├── |
| 功能 | 将输入能流取反输出 |
| SCL 等价 | NOT <能流条件> |
行为:
| 输入能流 | 输出能流 |
|---|---|
| 导通 | 断开 |
| 断开 | 导通 |
2.6 比较触点 (Comparison)
比较触点是一种特殊的触点,它有两个数据输入和一个布尔输出。当比较条件满足时,触点导通。
符号 (所有 6 种):
┌─ == ──┐ ┌─ <> ──┐ ┌─ > ────┐
──┤ IN1 ├── ──┤ IN1 ├── ──┤ IN1 ├──
│ IN2 │ │ IN2 │ │ IN2 │
└────────┘ └────────┘ └────────┘
┌─ < ────┐ ┌─ >= ──┐ ┌─ <= ──┐
──┤ IN1 ├── ──┤ IN1 ├── ──┤ IN1 ├──
│ IN2 │ │ IN2 │ │ IN2 │
└────────┘ └────────┘ └────────┘
参数表:
| 触点 | 符号 | 导通条件 | SCL 等价 |
|---|---|---|---|
| EQ (等于) | --[==]-- | IN1 = IN2 | IN1 = IN2 |
| NE (不等于) | --[<>]-- | IN1 <> IN2 | IN1 <> IN2 |
| GT (大于) | --[>]-- | IN1 > IN2 | IN1 > IN2 |
| LT (小于) | --[<]-- | IN1 < IN2 | IN1 < IN2 |
| GE (大于等于) | --[>=]-- | IN1 >= IN2 | IN1 >= IN2 |
| LE (小于等于) | --[<=]-- | IN1 <= IN2 | IN1 <= IN2 |
示例:
bEnable ┌─ GT ───┐ bAlarm
──┤ ├──────┤ rTemp ├───( )──
│ 80.0 │
└─────────┘
// rTemp > 80.0 时报警
// SCL: IF bEnable AND rTemp > 80.0 THEN bAlarm := TRUE; END_IF;
技巧:
- 比较触点支持所有基本数据类型:INT, DINT, REAL, TIME, DATE 等
- IN1 和 IN2 类型必须兼容(编辑器自动检查)
- 可以串联/并联使用,与其他触点组合
- 比较触点不能直接放在母线起始位置——前面需要一个能流输入
3. 线圈 (Coils)
线圈是梯形图中用于写入布尔变量的元件。根据线圈类型,可能受能流控制或触发行为。
3.1 标准线圈 (Coil)
符号:
──( )──
ASCII 表示:---( )---
参数:
| 属性 | 说明 |
|---|---|
| 符号 | --( )-- |
| 写入条件 | 能流导通时写 TRUE,断开时写 FALSE |
| SCL 等价 | <变量> := <能流条件>; |
| 典型用途 | 普通输出控制 |
示例:
bCond1 bCond2 bOut
──┤ ├──────┤/├──────────────────( )──
// bOut := bCond1 AND NOT bCond2;
技巧:
- 标准线圈是"随动"的——能流变它就变
- 如果同一个线圈在多个梯级中使用标准线圈,最后一个梯级的结果会覆盖前面的(危险! 反模式)
- 建议每个标准线圈只在一个梯级中使用
3.2 取反线圈 (Negated Coil)
符号:
──(/)──
ASCII 表示:---(/)---
参数:
| 属性 | 说明 |
|---|---|
| 符号 | --(/)-- |
| 写入条件 | 能流导通时写 FALSE,断开时写 TRUE |
| SCL 等价 | <变量> := NOT <能流条件>; |
| 典型用途 | 反相输出控制 |
示例:
bError bOK_Lamp
──┤ ├──────────────────────(/)──
// 错误时灯灭,正常时灯亮
// SCL: bOK_Lamp := NOT bError;
3.3 置位线圈 (Set / Latch)
符号:
──(S)──
ASCII 表示:---(S)---
参数:
| 属性 | 说明 |
|---|---|
| 符号 | --(S)-- |
| 写入条件 | 能流导通时置变量为 TRUE,断开时保持 |
| SCL 等价 | IF <能流条件> THEN <变量> := TRUE; END_IF; |
| 典型用途 | 自锁保持、状态锁存 |
示例:
bStart bMotorRun
──┤ ├──────────────────────(S)──
// bStart = TRUE 时置 bMotorRun 为 TRUE
// bStart 断开后 bMotorRun 保持 TRUE
// SCL: IF bStart THEN bMotorRun := TRUE; END_IF;
3.4 复位线圈 (Reset / Unlatch)
符号:
──(R)──
ASCII 表示:---(R)---
参数:
| 属性 | 说明 |
|---|---|
| 符号 | --(R)-- |
| 写入条件 | 能流导通时置变量为 FALSE,断开时保持 |
| SCL 等价 | IF <能流条件> THEN <变量> := FALSE; END_IF; |
| 典型用途 | 故障复位、状态清除 |
示例:
bStop bMotorRun
──┤ ├──────────────────────(R)──
// bStop = TRUE 时复位 bMotorRun 为 FALSE
// SCL: IF bStop THEN bMotorRun := FALSE; END_IF;
3.5 置位/复位组合模式 (Set-Reset Pattern)
最重要的编程模式:S/R 启停
bStart bMotor
──┤ ├──────────────────────(S)──
bStop bMotor
──┤ ├──────────────────────(R)──
// 启动时置位,停止时复位
// SCL: IF bStart THEN bMotor := TRUE; END_IF;
// IF bStop THEN bMotor := FALSE; END_IF;
技巧:
- S/R 比自锁电路更清晰(见设计原则章节)
- 使用 S(置位)线圈时,必须有对应的 R(复位)路径,否则可能导致输出"粘死"
- 置位/复位是"记忆"功能——即使能流消失,变量值也保持
3.6 中间变量线圈 (Midline Coil)
符号:
──(#)──
参数:
| 属性 | 说明 |
|---|---|
| 符号 | --(#)-- |
| 功能 | 在梯级中间暂存中间计算结果 |
| 典型用途 | 复杂组合逻辑的中间结果 |
示例:
bCond1 bCond2 bMid
──┤ ├───────┤ ├────────────────(#)──
bMid bCond3 bOut
──┤ ├───────┤ ├────────────────( )──
// bMid 存储 (bCond1 AND bCond2) 的中间结果
// bOut := bMid AND bCond3
3.7 保持线圈 (Memory Coil)
符号:
──(M)──
参数:
| 属性 | 说明 |
|---|---|
| 符号 | --(M)-- |
| 功能 | 与标准线圈类似,但断电保持(掉电后恢复) |
| 典型用途 | 掉电需保持的状态数据 |
技巧:
- 保持线圈在 PLC 断电重启后恢复为断电前的值
- 标准线圈和 S/R 线圈默认掉电复位
- 使用保持线圈需在变量声明中标记
RETAIN属性
3.8 置位优先 (SR) 与复位优先 (RS) 功能块
梯形图中也可以使用 SR 和 RS 功能块:
┌─ SR ─┐ ┌─ RS ─┐
│ S1 Q├──── bOut │ S Q├──── bOut
│ R │ │ R1 │
└───────┘ └───────┘
| 类型 | 冲突规则 | 说明 |
|---|---|---|
| SR (置位优先) | S 和 R 同时有效 → 置位 | 优先置位 |
| RS (复位优先) | S 和 R 同时有效 → 复位 | 优先复位(安全推荐) |
技巧:
- 安全回路推荐使用 RS(复位优先):冲突时安全优先(复位输出)
- SR 适合需要"启动优先"的场景
4. 定时器 (Timers)
定时器是梯形图中最常用的功能块之一。Darra IDE 支持三种 IEC 61131-3 标准定时器:TON、TOF、TP。
4.1 TON — 接通延时定时器
符号:
┌─ TON ─────┐
│ IN Q ├──── bDone
│ PT ET ├──── tElapsed
│ T#2s │
└────────────┘
参数:
| 引脚 | 类型 | 说明 |
|---|---|---|
IN | BOOL 输入 | 启动计时:TRUE 开始计时 |
PT | TIME 输入 | 预设延时时间 |
Q | BOOL 输出 | 计时完成输出 |
ET | TIME 输出 | 已计时时间 |
时序图:
IN ──┐ ┌────────────────
│ │
└──────────────┘
↑IN=TRUE开始计时
PT = T#3s
ET ──┐ ┌────
│ 3s │
└────────┘
Q ──────────────┐ ┌────
│ 3s 后 │
└────────┘
↑Q变TRUE
↑IN=FALSE复位
行为: IN 为 TRUE 时开始计时,ET 递增。当 ET >= PT 时 Q 变为 TRUE。IN 变为 FALSE 时 ET 清零,Q 变为 FALSE。
示例:
bTrigger ┌─ TON ─────┐ bDelayDone
──┤ ├────────┤ IN Q ├────( )──
│ PT ET │
│ T#3s │
└────────────┘
// bTrigger = TRUE 3 秒后 bDelayDone = TRUE
// SCL: ton(IN := bTrigger, PT := T#3s);
// bDelayDone := ton.Q;
技巧:
- TON 是最常用的定时器,适合"启动后延时动作"的场景
- PT 值可以用变量(如
tDelayTime),方便运行时调整 - 典型的 TON 应用:电机星三角启动延时、防颤振延时、报警确认延时
4.2 TOF — 断开延时定时器
符号:
┌─ TOF ─────┐
│ IN Q ├──── bDone
│ PT ET ├──── tElapsed
│ T#5s │
└────────────┘
参数:
| 引脚 | 类型 | 说明 |
|---|---|---|
IN | BOOL 输入 | FALSE 开始计时 |
PT | TIME 输入 | 断开延时时间 |
Q | BOOL 输出 | 延时期间保持 TRUE |
ET | TIME 输出 | 已计时时间 |
时序图:
IN ┌──────────────────┐
│ │
└──────────────────┘
↑IN=FALSE开始计时
Q ┌──────────────────┐
│ │
└──────────────────┘
↑5s后Q变FALSE
行为: IN 为 TRUE 时 Q 立即为 TRUE,ET = 0。IN 从 TRUE → FALSE 时开始计时,ET 递增。ET >= PT 时 Q 变为 FALSE。
示例:
bMotorRun ┌─ TOF ────┐ bCoolingFan
──┤ ├─────────┤ IN Q ├────( )──
│ PT T#5s │
└────────────┘
// 电机停止后风机继续运行 5 秒散热
// SCL: tof(IN := bMotorRun, PT := T#5s);
// bCoolingFan := tof.Q;
技巧:
- TOF 适合"停止后延时关断"的场景(如风机延时停止、冷却泵延时停止)
- 注意 TOF 的 Q 在 IN 为 TRUE 时立即为 TRUE——不是等 PT 时间后才 TRUE
4.3 TP — 脉冲定时器
符号:
┌─ TP ───────┐
│ IN Q ├──── bPulse
│ PT ET ├──── tElapsed
│ T#500ms │
└────────────┘
参数:
| 引脚 | 类型 | 说明 |
|---|---|---|
IN | BOOL 输入 | 上升沿触发脉冲 |
PT | TIME 输入 | 脉冲宽度 |
Q | BOOL 输出 | 脉冲输出 |
ET | TIME 输出 | 已计时时间 |
时序图:
IN ──┐ ┌──────┐ ┌──
│ │ │ │
└──┘ └─────────┘
↑上升沿触发
Q ┌────┐ ┌──────────┐
│ │ │ │
└────┘ └──────────┘
←PT宽度→ ←PT宽度→
↑后续触发不扩展
行为: IN 上升沿触发,Q 输出宽度为 PT 的脉冲。PT 期间后续上升沿不扩展脉冲。
示例:
bTrigger ┌─ TP ───────┐ bPulse
──┤P ├───────┤ IN Q ├────( )──
│ PT T#1s │
└────────────┘
// 每次上升沿触发,输出 1 秒脉冲
// SCL: tp(IN := bTrigger, PT := T#1s);
// bPulse := tp.Q;
4.4 定时器组合示例:闪烁灯
// 对称方波闪烁 (500ms ON / 500ms OFF)
bFlash ┌─ TP ───────┐ bFlash
──┤/├──────────────┤ IN Q ├───( )──
│ PT T#500ms │
└────────────┘
// bFlash = 500ms 脉冲 → 自反馈 → 持续闪烁
// 非对称方波 (1s ON / 2s OFF)
bTimerPulse ┌─ TON ────┐ bTimerPulse
──┤/├──────────┤ IN Q├───────( )──
│ PT T#1s │
└──────────┘
// 1s ON / 2s OFF 循环 (需要另一个定时器控制 OFF 时间)
定时器命名建议:
// 好:有意义的命名
tonMotorOverloadDelay
tofCoolingFanOff
tpAlarmFlash
// 避免:无意义命名
ton1
timer_3
t_abc
5. 计数器 (Counters)
计数器用于对脉冲信号进行计数。Darra IDE 支持三种 IEC 61131-3 标准计数器:CTU、CTD、CTUD。
5.1 CTU — 递增计数器
符号:
┌─ CTU ──────┐
│ CU Q ├──── bDone
│ R CV ├──── iCount
│ PV │
│ 10 │
└────────────┘
参数:
| 引脚 | 类型 | 说明 |
|---|---|---|
CU | BOOL 输入 | 上升沿计数+1 |
R | BOOL 输入 | 复位计数器(CV=0,Q=FALSE) |
PV | INT 输入 | 预设值 |
Q | BOOL 输出 | CV >= PV 时 TRUE |
CV | INT 输出 | 当前计数值 |
计数图:
CU ───┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌──
│ │ │ │ │ │ │ │ │ │ │ │
└──┘ └──┘ └──┘ └──┘ └──┘ └──┘
CV 0 1 2 3 4 5 ... 10
↑CV>=PV → Q=TRUE
R ┌────────────────────────────────────
│
└────────────────────────────────────
↑R复位 → CV=0, Q=FALSE
示例:
bSensor ┌─ CTU ──────┐ bFull
──┤P ├──────┤ CU Q ├───( )──
│ R CV ├── iCount
bReset │ PV │
──┤ ├───────┤ 100 │
└────────────┘
// 每检测到一个传感器脉冲,iCount+1
// 达到 100 时 bFull = TRUE
// SCL: ctu(CU := bSensor, R := bReset, PV := 100);
// bFull := ctu.Q; iCount := ctu.CV;
技巧:
- CU 信号建议使用上升沿检测(
┤P ├)后再接入,防止长脉冲多次计数 - PV 可以用变量,方便运行时修改
- 典型的 CTU 应用:产品计数、批次计数、脉冲累加
5.2 CTD — 递减计数器
符号:
┌─ CTD ──────┐
│ CD Q ├──── bDone
│ LD CV ├──── iCount
│ PV │
│ 5 │
└────────────┘
参数:
| 引脚 | 类型 | 说明 |
|---|---|---|
CD | BOOL 输入 | 上升沿计数-1 |
LD | BOOL 输入 | 加载预设值到 CV |
PV | INT 输入 | 预设值 |
Q | BOOL 输出 | CV <= 0 时 TRUE |
示例:
bConsume ┌─ CTD ──────┐ bEmpty
──┤P ├───────┤ CD Q ├───( )──
│ LD CV ├── iRemain
bLoad │ PV │
──┤ ├────────┤ 50 │
└────────────┘
// 每消耗一个产品 iRemain-1
// 到 0 时 bEmpty = TRUE
5.3 CTUD — 双向计数器
符号:
┌─ CTUD ────────┐
│ CU QU ├──── bUpDone
│ CD QD ├──── bDownDone
│ R CV ├──── iCount
│ LD │
│ PV │
│ 100 │
└───────────────┘
参数:
| 引脚 | 类型 | 说明 |
|---|---|---|
CU | BOOL 输入 | 上升沿计数+1 |
CD | BOOL 输入 | 上升沿计数-1 |
R | BOOL 输入 | 复位(CV=0,QU/QD=FALSE) |
LD | BOOL 输入 | 加载 PV 到 CV |
PV | INT 输入 | 预设值 |
QU | BOOL 输出 | CV >= PV 时 TRUE |
QD | BOOL 输出 | CV <= 0 时 TRUE |
CV | INT 输出 | 当前计数值 |
示例:库存管理
bInSensor ┌─ CTUD ────────┐ bFull
──┤P ├──────┤ CU QU ├───( )──
│ CD QD ├─── bEmpty
bOutSensor │ CV├── iStock
──┤P ├──────┤ R PV │
bReset │ LD 1000 │
──┤ ├───────┤ │
└───────────────┘
// iStock = 当前库存量
// 进料 +1,出料 -1,满仓报警,空仓报警
技巧:
- CTUD 适合库存管理、仓位计数、差值测量等场景
- CV 不会低于 0(递减到 0 后不再减少)
- 注意 CV 的数据类型,确保 PV 在类型范围内
6. 比较指令 (Comparison)
比较块有两个数据输入和一个布尔输出,输出由比较结果决定。
6.1 基本比较
符号 (6 种):
┌─ CMP ──┐ ┌─ == ──┐ ┌─ <> ──┐
──┤ IN1 ├── ──┤ IN1 ├── ──┤ IN1 ├──
│ IN2 │ │ IN2 │ │ IN2 │
└────────┘ └───────┘ └───────┘
参数表:
| 块 | 符号 | 条件 | SCL 等价 |
|---|---|---|---|
| EQ | --[==]-- | IN1 = IN2 | IN1 = IN2 |
| NE | --[<>]-- | IN1 <> IN2 | IN1 <> IN2 |
| GT | --[>]-- | IN1 > IN2 | IN1 > IN2 |
| LT | --[<]-- | IN1 < IN2 | IN1 < IN2 |
| GE | --[>=]-- | IN1 >= IN2 | IN1 >= IN2 |
| LE | --[<=]-- | IN1 <= IN2 | IN1 <= IN2 |
示例:温度超限报警
bEnable ┌─ GT ───┐ bAlarm
──┤ ├──────┤ rTemp ├───( )──
│ 80.0 │
└─────────┘
// rTemp > 80.0 时报警
// SCL: IF bEnable AND rTemp > 80.0 THEN bAlarm := TRUE; END_IF;
6.2 范围检查 (IN_RANGE / OUT_RANGE)
符号:
┌─ IN_RANGE ──┐ ┌─ OUT_RANGE ──┐
──┤ MN Q ├── ──┤ MN Q ├──
│ IN │ │ IN │
│ MX │ │ MX │
└──────────────┘ └───────────────┘
参数:
| 引脚 | 说明 |
|---|---|
MN | 最小值 |
IN | 被检测值 |
MX | 最大值 |
Q | 在范围内(IN_RANGE)或范围外(OUT_RANGE)时 TRUE |
示例:
┌─ IN_RANGE ─┐ bInRange
──┤ MN Q├───( )──
│ 0.0 │
│ rValue │
│ 100.0 │
└────────────┘
// 0.0 <= rValue <= 100.0 时 bInRange = TRUE
手动实现范围检查:
┌─ GE ───┐ ┌─ LE ───┐ bInRange
──┤ rValue ├────┤ rValue ├───( )──
│ 0.0 │ │ 100.0 │
└─────────┘ └─────────┘
// SCL: bInRange := (rValue >= 0.0) AND (rValue <= 100.0);
7. 数学运算 (Math)
数学运算块在 LAD 中以功能块形式出现,支持基本的算术和数学函数。
7.1 基本算术
符号:
┌─ ADD ──┐ ┌─ SUB ──┐ ┌─ MUL ──┐
──┤ IN1 ├── ──┤ IN1 ├── ──┤ IN1 ├──
│ IN2 │ │ IN2 │ │ IN2 │
│ ... │ └────────┘ └────────┘
└────────┘
参数表:
| 块 | 功能 | 输入数 | 说明 | SCL 等价 |
|---|---|---|---|---|
| ADD | 加法 | 2+ | IN1 + IN2 + ... | rSum := IN1 + IN2 |
| SUB | 减法 | 2 | IN1 - IN2 | rDiff := IN1 - IN2 |
| MUL | 乘法 | 2+ | IN1 * IN2 * ... | rProd := IN1 * IN2 |
| DIV | 除法 | 2 | IN1 / IN2 | rQuot := IN1 / IN2 |
| MOD | 取模 | 2 | IN1 MOD IN2 | iRem := IN1 MOD IN2 |
示例:求平均值
bCalc ┌─ ADD ────┐ ┌─ DIV ────┐ rAvg
──┤ ├────┤ rVal1 ├────┤ rSum ├───┤MOVE├──
│ rVal2 │ │ 3.0 │
│ rVal3 │ └───────────┘
└───────────┘
// rAvg = (rVal1 + rVal2 + rVal3) / 3
7.2 单变量数学函数
符号:
┌─ SQRT ─┐ ┌─ ABS ──┐ ┌─ NEG ──┐
──┤ IN1 ├── ──┤ IN1 ├── ──┤ IN1 ├──
└─────────┘ └────────┘ └────────┘
参数表:
| 块 | 功能 | 输入 | 输出 | SCL 等价 |
|---|---|---|---|---|
| ABS | 绝对值 | IN1 | |IN1| | ABS(IN1) |
| SQRT | 平方根 | IN1 | √IN1 | SQRT(IN1) |
| SQR | 平方 | IN1 | IN1² | IN1 * IN1 |
| NEG | 取反 | IN1 | -IN1 | -IN1 |
| LN | 自然对数 | IN1 | ln(IN1) | LN(IN1) |
| LOG | 常用对数 | IN1 | log10(IN1) | LOG(IN1) |
| EXP | 指数 | IN1 | e^IN1 | EXP(IN1) |
7.3 三角函数
符号:
┌─ SIN ──┐ ┌─ COS ──┐ ┌─ TAN ──┐
──┤ IN1 ├── ──┤ IN1 ├── ──┤ IN1 ├──
└─────────┘ └────────┘ └────────┘
参数表:
| 块 | 功能 | 输入单位 | SCL 等价 |
|---|---|---|---|
| SIN | 正弦 | 弧度 | SIN(IN1) |
| COS | 余弦 | 弧度 | COS(IN1) |
| TAN | 正切 | 弧度 | TAN(IN1) |
| ASIN | 反正弦 | 输出弧度 | ASIN(IN1) |
| ACOS | 反余弦 | 输出弧度 | ACOS(IN1) |
| ATAN | 反正切 | 输出弧度 | ATAN(IN1) |
示例:计算斜边长度
bCalc ┌─ SQR ──┐ ┌─ ADD ──┐ ┌─ SQRT ─┐ rHypotenuse
──┤ ├──────┤ rSideA ├────┤ rASq ├────┤ rSum ├───┤MOVE├──
└─────────┘ │ rBSq │ └──────────┘
┌─ SQR ──┐ └──────────┘
│ rSideB ├───┘
└─────────┘
// rHypotenuse = SQRT(SQR(rSideA) + SQR(rSideB))
8. 移动指令 (Move)
移动指令用于在变量之间复制数据。
8.1 MOVE — 赋值
符号:
┌─ MOVE ─┐
──┤ IN OUT├──
└─────────┘
参数:
| 属性 | 说明 |
|---|---|
| 功能 | 当能流导通时,将输入值复制到输出 |
| SCL 等价 | IF <能流> THEN <OUT> := <IN>; END_IF; |
| 数据类型 | 任意基本类型(自动匹配) |
示例:
bLoad ┌─ MOVE ─┐ rSetpoint
──┤ ├─────────┤ IN OUT├───
│ 100.0 │
└─────────┘
// rSetpoint := 100.0;
8.2 MOVE_BLK — 块传输
符号:
┌─ MOVE_BLK ───┐
──┤ ENABLE DONE├──
│ SRC ERR ├──
│ DST ERRNO├──
│ COUNT │
└──────────────┘
参数:
| 引脚 | 类型 | 说明 |
|---|---|---|
ENABLE | BOOL 输入 | 上升沿触发传输 |
SRC | 任意数组 | 源数组 |
DST | 任意数组 | 目标数组 |
COUNT | UDINT 输入 | 传输元素数 |
DONE | BOOL 输出 | 传输完成 |
ERR | BOOL 输出 | 错误标志 |
示例:
bTrigger ┌─ MOVE_BLK ──┐ bDone
──┤P ├───────┤ ENABLE DONE├───( )──
│ SRC ERR │
arSource ├─────────────┤
arDest ├──DST │
│ COUNT=50 │
└─────────────┘
// 将 arSource[0..49] 复制到 arDest[0..49]
8.3 FILL — 数组填充
符号:
┌─ FILL ────────┐
──┤ ENABLE DONE├──
│ VALUE ERR ├──
│ DST ERRNO ├──
│ COUNT │
└───────────────┘
参数:
| 引脚 | 类型 | 说明 |
|---|---|---|
ENABLE | BOOL 输入 | 上升沿触发填充 |
VALUE | 任意类型 | 填充值 |
DST | 数组 | 目标数组 |
COUNT | UDINT 输入 | 填充元素数 |
示例:
bInit ┌─ FILL ───────┐ bDone
──┤P ├───────┤ ENABLE DONE ├───( )──
│ VALUE ERR │
0 ├──────────────┤
arBuffer ├──DST │
│ COUNT=100 │
└──────────────┘
// 将 arBuffer[0..99] 全部填充为 0
8.4 SWAP — 字节交换
符号:
┌─ SWAP ──┐
──┤ IN OUT├──
└─────────┘
参数:
| 引脚 | 类型 | 说明 |
|---|---|---|
IN | WORD/DWORD | 输入值 |
OUT | WORD/DWORD | 字节交换后的值 |
示例:
bSwap ┌─ SWAP ──┐ wSwapped
──┤ ├────────┤ IN OUT├───
│ 16#1234 │
└──────────┘
// wSwapped = 16#3412 (高低字节交换)
9. 转换指令 (Convert)
转换指令用于数据类型之间的显式转换。
9.1 类型转换
符号:
┌─ INT_TO_REAL ─┐
──┤ IN OUT├──
└───────────────┘
常用转换:
| 块 | 功能 | 说明 |
|---|---|---|
INT_TO_REAL | INT → REAL | 整数转浮点数 |
REAL_TO_INT | REAL → INT | 浮点数转整数(截断) |
BCD_TO_INT | BCD → INT | BCD 码转整数 |
INT_TO_BCD | INT → BCD | 整数转 BCD 码 |
DINT_TO_REAL | DINT → REAL | 双整数转浮点数 |
REAL_TO_DINT | REAL → DINT | 浮点数转双整数 |
WORD_TO_INT | WORD → INT | 字转整数 |
INT_TO_WORD | INT → WORD | 整数转子 |
示例:
bConvert ┌─ INT_TO_REAL ─┐ rValue
──┤ ├────────┤ IN OUT├───
│ iCount │
└───────────────┘
// rValue := INT_TO_REAL(iCount);
9.2 缩放 (SCALE)
符号:
┌─ SCALE ───────┐
──┤ ENABLE DONE├──
│ IN OUT ├── rScaled
│ LO_LIM │
│ HI_LIM │
└───────────────┘
示例: 将 4-20mA 信号(0-27648)映射为 0-100%:
bRead ┌─ SCALE ───────┐ bDone
──┤ ├────────┤ ENABLE DONE├───( )──
│ IN OUT ├── rPercent
iAnalogIn ├───────────────┤
│ LO_LIM = 0 │
│ HI_LIM = 100 │
└───────────────┘
// rPercent = 0~100 对应 iAnalogIn 0~27648
10. 程序控制 (Program Control)
程序控制指令改变程序的执行流程。
10.1 JMP — 跳转
符号:
┌─ JMP ────┐
──┤ LBL_Name ├──
└──────────┘
参数:
| 属性 | 说明 |
|---|---|
| 功能 | 当能流导通时,跳转到同 POU 内的指定标签 |
| SCL 等价 | GOTO LBL_Name |
| 注意事项 | 跳转后的梯级被跳过不执行 |
示例:
bSkip bOut1
──┤ ├────[JMP LBL_Skip]──( )──
// 当 bSkip = TRUE 时跳转到 LBL_Skip
// bOut1 不受影响(已先执行)
bCond1 bOut2
──┤ ├──────( )──
// 被跳过的梯级
[LBL_Skip]
// 跳转目标
bCond3 bOut3
──┤ ├──────( )──
技巧:
- JMP 会跳过中间所有梯级,直接到 LBL 位置
- 跳转不能跨越 POU 边界(不能跳到其他 FB/FC 中)
- 避免滥用 JMP——过多的跳转会破坏程序的可读性
- 能用 S/R 顺序控制代替的,优先使用 S/R
10.2 LBL — 标签
符号:
[LBL_Name]
参数:
| 属性 | 说明 |
|---|---|
| 功能 | 定义跳转目标位置 |
| 命名规则 | 字母、数字、下划线,首字符不能是数字 |
10.3 RET — 返回
符号:
──[RET]──
参数:
| 属性 | 说明 |
|---|---|
| 功能 | 当能流导通时,立即结束当前 POU 的执行,返回调用者 |
| SCL 等价 | RETURN |
示例:
bCondition
──┤ ├────[RET]──
// 条件满足时提前返回
bNormalRun
──┤ ├──────( )──
// 被跳过的代码
技巧:
- RET 适合在 POU 开头做前置条件检查
- 不满足条件时提前返回,避免深层嵌套
10.4 END — 程序结束
符号:
──[END]──
参数:
| 属性 | 说明 |
|---|---|
| 功能 | 结束当前扫描周期的程序执行 |
| 说明 | 通常在每个 POU 末尾隐式存在,显式使用用于提前结束 |
10.5 CALL — 调用子程序
符号:
┌─ CALL ────────┐
──│ FC_MyFunction │──
│ IN1= OUT1= │
│ IN2= OUT2= │
└──────────────┘
参数:
| 属性 | 说明 |
|---|---|
| 功能 | 调用函数 (FC) 或功能块 (FB) |
| SCL 等价 | FC_MyFunction(IN1:=..., IN2:=...); |
示例:
bEnable ┌─ CALL ────────────┐
──┤ ├───────┤ FC_CalcDistance │
│ rX1=100.0 rDist├── rResult
│ rY1=200.0 │
│ rX2=rTargetX │
│ rY2=rTargetY │
└──────────────────┘
11. 位逻辑指令 (Bit Logic)
位逻辑指令用于操作字/双字中的特定位。
11.1 SET_BIT — 置位
符号:
┌─ SET_BIT ─┐
──│ IN OUT├──
│ INDEX │
└───────────┘
参数:
| 引脚 | 类型 | 说明 |
|---|---|---|
IN | WORD/DWORD | 输入值 |
INDEX | UINT 输入 | 位索引(0 |
OUT | WORD/DWORD | 输出值(指定位已置1) |
示例:
bSet ┌─ SET_BIT ─┐ wResult
──┤ ├────────┤ IN OUT├───
│ INDEX=3 │
│ 16#0000 │
└───────────┘
// wResult = 16#0008 (bit 3 置 1)
11.2 CLR_BIT — 清零
符号:
┌─ CLR_BIT ─┐
──│ IN OUT├──
│ INDEX │
└───────────┘
示例:
bClear ┌─ CLR_BIT ─┐ wResult
──┤ ├────────┤ IN OUT├───
│ INDEX=7 │
│ 16#00FF │
└───────────┘
// wResult = 16#007F (bit 7 清 0)
11.3 TEST_BIT — 测试位
符号:
┌─ TEST_BIT ─┐
──│ IN ├── (导通 = 该位为 1)
│ INDEX │
└────────────┘
示例:
┌─ TEST_BIT ─┐ bBit3Set
──┤ wStatus ├───( )──
│ INDEX=3 │
└────────────┘
// wStatus 的 bit 3 = 1 时 bBit3Set = TRUE
12. 位移指令 (Shift)
位移指令用于对字/双字进行移位或循环操作。
12.1 SHL — 左移
符号:
┌─ SHL ──┐
──│ IN OUT├──
│ N │
└────────┘
参数:
| 引脚 | 类型 | 说明 |
|---|---|---|
IN | 任意整数类型 | 输入值 |
N | UINT 输入 | 移位数 |
OUT | 同 IN | 输出值 |
示例:
bShift ┌─ SHL ──┐ wResult
──┤ ├────────┤ IN OUT├───
│ N=2 │
│ 16#0001 │
└─────────┘
// wResult = 16#0004 (左移 2 位,等价于乘 4)
12.2 SHR — 右移
符号:
┌─ SHR ──┐
──│ IN OUT├──
│ N │
└────────┘
示例:
bShift ┌─ SHR ──┐ wResult
──┤ ├────────┤ IN OUT├───
│ N=2 │
│ 16#0008 │
└─────────┘
// wResult = 16#0002 (右移 2 位,等价于除 4)
12.3 ROL — 循环左移
符号:
┌─ ROL ──┐
──│ IN OUT├──
│ N │
└────────┘
示例:
bRotate ┌─ ROL ──┐ wResult
──┤ ├────────┤ IN OUT├───
│ N=4 │
│ 16#F001 │
└─────────┘
// wResult = 16#001F (左移 4 位,高位移到低位)
12.4 ROR — 循环右移
符号:
┌─ ROR ──┐
──│ IN OUT├──
│ N │
└────────┘
示例:
bRotate ┌─ ROR ──┐ wResult
──┤ ├────────┤ IN OUT├───
│ N=4 │
│ 16#000F │
└─────────┘
// wResult = 0xF000 (右移 4 位,低位移到高位)
技巧:
- 左移 1 位等价于乘 2(无符号数)
- 右移 1 位等价于除 2(无符号数)
- ROL/ROR 适合做校验和计算、LED 跑马灯效果
13. 功能块调用 (FB/FC Call)
在 LAD 中可以调用 SCL 编写的自定义功能块 (FB) 或函数 (FC),表现形式与标准定时器相同。
13.1 FB 实例调用
功能块 (FB) 是有状态的——每次调用后内部变量保持:
bEnable ┌─ FB_Motor ─────────┐
──┤ ├──────┤ bStart bRunning├── bMotorOn
│ rSetSpeed rActSpeed├── rFeedback
bStop │ │
──┤/├──────┤ bStop sDiagMsg├── sStatus
└─────────────────────┘
13.2 FC 函数调用
函数 (FC) 是无状态的,每次调用独立计算:
bEnable ┌─ FC_CalcDistance ─┐
──┤ ├──────┤ rX1 rDist├── rResult
│ rY1 │
│ rX2 │
│ rY2 │
└───────────────────┘
13.3 输入输出参数绑定
在 LAD 中调用 FB/FC 时,每个参数端口需要绑定变量:
| 参数类型 | 绑定方式 | 说明 |
|---|---|---|
| VAR_INPUT | 左侧连接变量 | 从 LAD 梯级传入值 |
| VAR_OUTPUT | 右侧输出变量 | 输出到 LAD 梯级 |
| VAR_IN_OUT | 双向连接 | 同一个变量同时输入输出 |
| VAR (内部) | 不显示 | FB 内部状态,自动管理 |
14. 实际应用示例
14.1 电机启停控制
功能: 带过载保护的三相电机启动/停止,含运行指示和运行计时。
// === 安全联锁 ===
bEStop bSafetyGate bSafetyOK
──┤/├────────┤/├─────────────────( )──
// === 启动/停止(S/R 方式) ===
bStart bStop bMotorRun
──┤ ├────────┤ ├────┬────────────(S)──
│
bMotorRun │
──┤ ├────────────────┘
// === 过载保护 ===
bOverload bMotorRun
──┤/├─────────────────────(R)──
// === 输出到接触器(串联安全联锁) ===
bMotorRun bSafetyOK bContactor
──┤ ├────────┤ ├─────────────────( )──
// === 运行指示 ===
bMotorRun bRunLight
──┤ ├────────────────────────────( )──
// === 运行计时 ===
bMotorRun ┌─ TON ────┐ bRunHourReached
──┤ ├────────┤ IN Q├───────( )──
│ PT T#8h │
└──────────┘
SCL 等价:
// 安全联锁
bSafetyOK := NOT bEStop AND NOT bSafetyGate;
// 启停
IF (bStart OR bMotorRun) AND NOT bStop THEN
bMotorRun := TRUE;
END_IF;
// 过载保护
IF NOT bOverload THEN
bMotorRun := FALSE;
END_IF;
// 输出
bContactor := bMotorRun AND bSafetyOK;
bRunLight := bMotorRun;
// 计时
tonRunTime(IN := bMotorRun, PT := T#8h);
bRunHourReached := tonRunTime.Q;
14.2 交通灯控制
功能: 单路口红绿灯时序控制(红灯 30s → 绿灯 25s → 黄灯 3s)。
// === 启动 ===
bStart bSystemRun
──┤P├──────────────────────(S)──
// === 红灯阶段 ===
bSystemRun tonGreen.Q bRed
──┤ ├────────┤/├───────────(S)──
bRed tonRed
──┤ ├──────────────────────( )── // 实际接 TON
tonRed.Q ┌─ TON ────┐ tonRed
──┤ ├────────┤ IN Q├───( )──
│ PT T#30s │
└──────────┘
tonRed.Q bRed
──┤ ├──────────────────────(R)──
// === 绿灯阶段 ===
tonRed.Q bYellow.Q bGreen
──┤P├────────┤/├──────────(S)──
bGreen tonGreen
──┤ ├──────────────────────( )── // 实际接 TON
tonGreen.Q ┌─ TON ────┐ tonGreen
──┤ ├────────┤ IN Q├───( )──
│ PT T#25s │
└──────────┘
tonGreen.Q bGreen
──┤P├──────────────────────(R)──
// === 黄灯阶段 ===
tonGreen.Q bRed bYellow
──┤P├────────┤/├──────────(S)──
bYellow tonYellow
──┤ ├──────────────────────( )── // 实际接 TON
tonYellow.Q ┌─ TON ────┐ tonYellow
──┤ ├────────┤ IN Q├───( )──
│ PT T#3s │
└──────────┘
tonYellow.Q bYellow
──┤P├──────────────────────(R)──
// === 停止 ===
bStop bSystemRun
──┤ ├──────────────────────(R)──
bStop bRed
──┤ ├──────────────────────(R)──
bStop bGreen
──┤ ├──────────────────────(R)──
bStop bYellow
──┤ ├──────────────────────(R)──
14.3 传送带控制
功能: 传送带启动/停止、过载报警、堵料检测。
// === 启停控制 ===
bStart bStop bConveyor
──┤ ├──────┤/├────────────────────(S)──
bConveyor
──┤ ├──────┘
// === 过载报警 (rCurrent > 15.0A) ===
bEnable ┌─ GT ───┐ bAlarmOverload
──┤ ├───────┤ rCurrent├───────────(S)──
│ 15.0 │
└────────┘
// === 跑偏检测(传感器持续 2s 触发)===
bMisalign ┌─ TON ────┐ bAlarmMisalign
──┤ ├─────────┤ IN Q├──────(S)──
│ PT T#2s │
└──────────┘
// === 堵料检测(电机运行但无物料通过超过 10s)===
bConveyor bPartDetect bJamDelay
──┤ ├────────┤/├─────────────────(S)──
bJamDelay ┌─ TON ────┐ bAlarmJam
──┤ ├─────────┤ IN Q├──────(S)──
│ PT T#10s │
└──────────┘
// === 报警复位 ===
bReset bAlarmOverload
──┤ ├──────────────────────────(R)──
bReset bAlarmMisalign
──┤ ├──────────────────────────(R)──
bReset bAlarmJam
──┤ ├──────────────────────────(R)──
// === 蜂鸣器(任一报警激活)===
bAlarmOverload bBuzzer
──┤ ├────────────────────────────( )──
bAlarmMisalign
──┤ ├──
bAlarmJam
──┤ ├──
14.4 报警系统
功能: 三级报警:警告、报警、紧急。
// === 温度三级报警 ===
// Level 1: 警告 (rTemp > 60°C)
┌─ GT ───┐ bWarn
──┤ rTemp ├───────────────────(S)──
│ 60.0 │
└────────┘
// Level 2: 报警 (rTemp > 80°C)
┌─ GT ───┐ bAlarm
──┤ rTemp ├───────────────────(S)──
│ 80.0 │
└────────┘
// Level 3: 紧急 (rTemp > 100°C)
┌─ GT ───┐ bEmergency
──┤ rTemp ├───────────────────(S)──
│ 100.0 │
└────────┘
// === 恢复正常自动清除 ===
┌─ LE ───┐ bWarn
──┤ rTemp ├───────────────────(R)──
│ 55.0 │
└────────┘
┌─ LE ───┐ bAlarm
──┤ rTemp ├───────────────────(R)──
│ 75.0 │
└────────┘
┌─ LE ───┐ bEmergency
──┤ rTemp ├───────────────────(R)──
│ 95.0 │
└────────┘
// === 报警指示灯(带闪烁)===
bEmergency bFlash bRedLight
──┤ ├────────┤ ├──────────────────( )──
bAlarm bWarn bYellowLight
──┤ ├────────┤ ├──────────────────( )──
14.5 安全回路
功能: 符合 ISO 13849 的安全回路设计。
// === 急停链 ===
// 所有急停按钮串联,常闭触点(断线检测优先)
bES1 bES2 bES3 bES_ChainOK
──┤/├───────┤/├───────┤/├─────────────────( )──
// 急停状态指示
bES_ChainOK bES_Normal
──┤ ├─────────────────────────────────────( )──
// === 安全门监控 ===
bDoorClosed bDoorLocked bDoorOK
──┤ ├─────────┤ ├──────────────────────( )──
// 门未关报警(延时确认,防抖动)
bDoorOK ┌─ TON ────┐ bDoorAlarm
──┤/├────────┤ IN Q├──────────────(S)──
│ PT T#1s │
└──────────┘
// === 双手启动(ISO 13851)===
// 双手按钮同时按下 0.5s 内启动
bHandLeft bHandRight ┌─ TON ────┐ bStartOK
──┤ ├───────┤ ├──────────┤ IN Q├──( )──
│ PT T#500ms│
└──────────┘
// === 安全输出 ===
bES_ChainOK bDoorOK bStartOK bMachineRun
──┤ ├─────────┤ ├────────┤P├──────────────(S)──
bES_ChainOK bMachineRun
──┤/├──────────────────────────────────────(R)──
14.6 顺序控制(气动阀门)
功能: 双气缸顺序动作——A 缸伸出→B 缸伸出→B 缸退回→A 缸退回。
// === 双气缸顺序控制 ===
// Step 1: A 缸伸出
bCycleStart bStep4Done bStep1
──┤ ├────────┤/├──────────────────(S)──
bStep1 bAExtEnd bStep2
──┤ ├────────┤ ├────┬─────────────(S)──
│
bStep1 (R)──
// Step 2: B 缸伸出
bStep2 bBExtEnd bStep3
──┤ ├────────┤ ├────┬─────────────(S)──
│
bStep2 (R)──
// Step 3: B 缸退回
bStep3 bBRetEnd bStep4
──┤ ├────────┤ ├────┬─────────────(S)──
│
bStep3 (R)──
// Step 4: A 缸退回
bStep4 bARetEnd bCycleDone
──┤ ├────────┤ ├────┬─────────────(S)──
│
bStep4 (R)──
// 输出映射
bStep1 bAExtend
──┤ ├────────────────────────────( )──
bStep2 bBExtend
──┤ ├────────────────────────────( )──
bStep3 bBRetract
──┤ ├────────────────────────────( )──
bStep4 bARetract
──┤ ├────────────────────────────( )──
15. 调试与监视
Darra IDE 提供完整的 LAD 在线调试能力。
15.1 在线监视 (Online Monitoring)
当 PLC 运行时,LAD 编辑器进入在线监视模式:
// 导通着色:绿色 = 能流导通,灰色 = 能流断开
bStart bStop bMotor ← 梯级注释
──┤[ ]├────┤[/]├────┬──────( )── ← bStart=绿色(通)
│ bStop=灰色(断)
bMotor │ bMotor=绿色(通)
──┤[ ]├──────────────┘
- 绿色高亮:该元件当前导通(能流通过)
- 灰色/原色:该元件当前断开
- 变量悬浮:鼠标悬停在变量上显示当前值
- 实时更新:每个扫描周期刷新一次
15.2 强制值 (Force)
在在线模式下可以强制变量为指定值,用于测试:
// 强制 bMotor 为 TRUE(即使能流条件不满足)
bStart bStop bMotor
──┤[ ]├────┤[/]├────┬──────([F])── ← [F] = 强制标志
│
bMotor │
──┤[ ]├──────────────┘
- 强制值以紫色/粉色高亮显示
- 强制操作记录在强制日志中
- 取消强制后恢复为程序控制值
15.3 断点模式 (Breakpoint)
LAD 支持梯级级断点:
⚫ bStart bStop bMotor ← ⚫ = 断点
──┤[ ]├────┤[/]├────┬──────( )──
│
bMotor │
──┤[ ]├──────────────┘
- 右键梯级号 → 切换断点
- 断点命中时 PLC 暂停该 POU 的执行
- 支持条件断点(某变量=特定值时触发)
- 支持断点计数(第 N 次命中时才停)
15.4 趋势图 (Trend Chart)
趋势图以曲线形式显示变量值随时间的变化:
值
100┤ ┌────────────────────
│ │╱╲ ╱╲
80┤ ──╲──╲──╱──╲────────
│ ╲ ╱ ╲
60┤ ────╲╱───────╲───────
│ ╲
40┤ ────────────────╲─────
│ ╲
20┤ ──────────────────╲───
│ ╲
0┴─────────────────────╲──
0 5 10 15 20 时间(s)
- 支持同时显示多个变量
- 可自定义采样周期和显示范围
- 趋势数据可导出为 CSV
16. 附录:元件速查表
触点速查
| 符号 | 名称 | 导通条件 | SCL 等价 |
|---|---|---|---|
--[ ]-- | 常开触点 (NO) | 变量 = TRUE | IF var THEN |
--[/]-- | 常闭触点 (NC) | 变量 = FALSE | IF NOT var THEN |
--[P]-- | 上升沿检测 | FALSE→TRUE 瞬间 | R_TRIG(CLK:=v).Q |
--[N]-- | 下降沿检测 | TRUE→FALSE 瞬间 | F_TRIG(CLK:=v).Q |
--[NOT]-- | 取反 | 输入断开时 | NOT condition |
--[==]-- | 等于比较 | IN1 = IN2 | IN1 = IN2 |
--[<>]-- | 不等于比较 | IN1 <> IN2 | IN1 <> IN2 |
--[>]-- | 大于比较 | IN1 > IN2 | IN1 > IN2 |
--[<]-- | 小于比较 | IN1 < IN2 | IN1 < IN2 |
--[>=]-- | 大于等于 | IN1 >= IN2 | IN1 >= IN2 |
--[<=]-- | 小于等于 | IN1 <= IN2 | IN1 <= IN2 |
线圈速查
| 符号 | 名称 | 写入条件 | SCL 等价 |
|---|---|---|---|
--( )-- | 标准线圈 | 导通=TRUE, 断开=FALSE | v := cond |
--(/)-- | 取反线圈 | 导通=FALSE, 断开=TRUE | v := NOT cond |
--(S)-- | 置位线圈 | 导通=TRUE, 断开保持 | IF cond THEN v:=TRUE |
--(R)-- | 复位线圈 | 导通=FALSE, 断开保持 | IF cond THEN v:=FALSE |
--(M)-- | 保持线圈 | 同标准线圈,断电保持 | v := cond (RETAIN) |
定时器速查
| 类型 | 触发 | Q 行为 | 复位条件 |
|---|---|---|---|
| TON | IN=TRUE 开始计时 | 延时后 Q=TRUE | IN=FALSE 时 ET 清零 |
| TOF | IN→FALSE 开始计时 | IN=TRUE 时 Q 立即 TRUE | 计时结束 Q=FALSE |
| TP | IN 上升沿触发 | Q 输出固定宽度脉冲 | PT 到期后 Q=FALSE |
计数器速查
| 类型 | 计数方向 | 复位 | 输出条件 |
|---|---|---|---|
| CTU | 递增 (CU) | R 复位 | CV >= PV 时 Q=TRUE |
| CTD | 递减 (CD) | LD 加载 PV | CV <= 0 时 Q=TRUE |
| CTUD | 双向 (CU+CD) | R 复位 + LD 加载 | QU: CV>=PV; QD: CV<=0 |
数学运算速查
| 块 | 输入 | 输出 | 说明 |
|---|---|---|---|
| ADD | 2+ 个 | 和 | IN1 + IN2 + ... |
| SUB | 2 个 | 差 | IN1 - IN2 |
| MUL | 2+ 个 | 积 | IN1 * IN2 * ... |
| DIV | 2 个 | 商 | IN1 / IN2 |
| MOD | 2 个 | 余数 | IN1 MOD IN2 |
| ABS | 1 个 | 绝对值 | |IN| |
| SQRT | 1 个 | 平方根 | √IN (IN >= 0) |
| SQR | 1 个 | 平方 | IN² |
| NEG | 1 个 | 取反 | -IN |
| SIN | 1 个 | 正弦 | sin(IN) 弧度 |
| COS | 1 个 | 余弦 | cos(IN) 弧度 |
| TAN | 1 个 | 正切 | tan(IN) 弧度 |
移动/转换速查
| 块 | 功能 | 说明 |
|---|---|---|
| MOVE | 赋值 | IN → OUT |
| MOVE_BLK | 块传输 | 数组间批量复制 |
| FILL | 填充 | 数组全部设为同一值 |
| SWAP | 字节交换 | 高低字节互换 |
| SCALE | 缩放 | 输入值线性映射到新范围 |
程序控制速查
| 块 | 功能 | 说明 |
|---|---|---|
| JMP | 跳转到标签 | 跳过中间梯级 |
| LBL | 标签定义 | 跳转目标 |
| RET | 返回 | 提前结束 POU |
| END | 程序结束 | 结束当前扫描 |
| CALL | 调用子程序 | 调用 FC/FB |
位逻辑与位移速查
| 块 | 功能 | 说明 |
|---|---|---|
| SET_BIT | 置位 | 指定位置 1 |
| CLR_BIT | 清零 | 指定位置 0 |
| TEST_BIT | 测试 | 测试指定位的值 |
| SHL | 左移 | 按位左移 N 位 |
| SHR | 右移 | 按位右移 N 位 |
| ROL | 循环左移 | 循环左移 N 位 |
| ROR | 循环右移 | 循环右移 N 位 |
设计原则
P1. 每级只做一个逻辑功能
每个梯级应实现一个独立、完整的逻辑功能。避免将多个不相关的逻辑塞入同一梯级。
// 推荐:每级一个功能
// 梯级 1: 电机启动条件
bStart bStop bOverload bMotorRun
──┤ ├──────┤/├──────┤/├──────────────( )──
// 梯级 2: 运行指示
bMotorRun bMotorIndicator
──┤ ├────────────────────( )──
// 梯级 3: 计时
bMotorRun ┌─ TON ────┐ bRunTimeOK
──┤ ├────────┤ IN Q├───( )──
│ PT T#1h│
└──────────┘
P2. 安全信号串在最前
急停、安全门、光栅等安全相关信号应串联在所有输出线圈之前,使用常闭触点形式。
// 安全联锁 — 在所有梯级之前
bEStop bSafetyGate bLightCurtain bSafetyOK
──┤/├──────┤/├───────────┤/├───────────────( )──
// 每个输出梯级引用 bSafetyOK
bStart bSafetyOK bMotor
──┤ ├──────┤ ├─────────────────────( )──
P3. 优先使用 S/R 代替自锁
置位/复位线圈逻辑比自锁电路更清晰,不容易出现"意外保持"的 bug。
// 推荐:S/R 方式
bStart bMotorRun
──┤ ├─────────────────────(S)──
bStop bMotorRun
──┤ ├─────────────────────(R)──
// 避免:自锁方式(可读性差,易出错)
bStart bStop bMotorRun
──┤ ├──────┤/├────┬───────────────( )──
│
bMotorRun │
──┤ ├──────────────┘
P4. 显式复位所有 S 线圈
使用 S(置位)线圈时,必须有对应的 R(复位)路径,否则可能导致输出"粘死"。
P5. 定时器/计数器实例命名清晰
// 好:有意义的命名
tonMotorOverloadDelay
ctuPartCount_Line1
tofCoolingFanOff
// 避免:无意义命名
ton1
ctu2
timer_3
性能优化建议
- 梯级数量控制:单个 POU 梯级不超过 50 级,超过则拆分子程序
- 减少分支嵌套:分支深度不超过 4 层,过深影响扫描效率
- 避免空梯级:空梯级浪费扫描时间,及时清理
- 使用 MOVE 代替多个线圈:需要同时赋多个值的场景,考虑用 MOVE 块一次赋值
- 定时器 PT 不要频繁修改:PT 值变化需重新初始化定时器
- 高速任务用 SCL:1ms 以下周期任务建议用 SCL 替代 LAD
常见反模式
| 反模式 | 问题 | 正确做法 |
|---|---|---|
| 线圈双向驱动 | 同一线圈在多个梯级赋值 | 合并到一个梯级或用 S/R |
| 空线圈悬空 | 线圈未绑定变量 | 确认每个线圈都有有效变量 |
| 触点直接连母线 | 左母线直连右母线,短路 | 加中间变量或空线圈 |
| 定时器嵌套过深 | 定时器输出再驱动定时器 | 用顺序逻辑替代嵌套 |
| 分支未闭合 | 分支有头无尾 | 确保分支汇合到公共路径 |
| 跳转滥用 | JMP 满天飞,逻辑不连续 | 用 S/R 顺序控制替代 |
| 变量类型混用 | INT 直接连 BOOL 输入 | 用比较块转换 |