跳到主要内容

LAD 梯形图完全参考手册

梯形图 (Ladder Diagram, LAD) 是 IEC 61131-3 标准定义的 PLC 编程语言之一,也是工业自动化领域最经典、最直观的编程方式。Darra IDE 提供完整的 LAD 编辑器,支持从简单开关逻辑到复杂功能块调用的全范围编程。

本文是一站式 LAD 参考手册,按照 "菜鸟教程"风格编排,涵盖所有元件、参数、示例和最佳实践。如需编辑操作指南,请参阅 LAD 编辑器;如需调试方法,请参阅 LAD 调试


目录

  1. LAD 梯形图入门
  2. 触点 (Contacts)
  3. 线圈 (Coils)
  4. 定时器 (Timers)
  5. 计数器 (Counters)
  6. 比较指令 (Comparison)
  7. 数学运算 (Math)
  8. 移动指令 (Move)
  9. 转换指令 (Convert)
  10. 程序控制 (Program Control)
  11. 位逻辑指令 (Bit Logic)
  12. 位移指令 (Shift)
  13. 功能块调用 (FB/FC Call)
  14. 实际应用示例
  15. 调试与监视
  16. 附录:元件速查表

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 执行在此阶段完成
  1. 读取输入 — 采样物理输入到过程映像区 (PII)
  2. 执行梯级 — 按梯级顺序逐级执行,每级内部从左到右
  3. 更新输出 — 将结果写入物理输出 (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 = IN2IN1 = IN2
NE (不等于)--[&lt;&gt;]--IN1 <> IN2IN1 &lt;&gt; IN2
GT (大于)--[&gt;]--IN1 > IN2IN1 &gt; IN2
LT (小于)--[&lt;]--IN1 < IN2IN1 &lt; IN2
GE (大于等于)--[&gt;=]--IN1 >= IN2IN1 &gt;= IN2
LE (小于等于)--[&lt;=]--IN1 <= IN2IN1 &lt;= 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 等价&lt;变量&gt; := &lt;能流条件&gt;;
典型用途普通输出控制

示例:

     bCond1     bCond2               bOut
──┤ ├──────┤/├──────────────────( )──
// bOut := bCond1 AND NOT bCond2;

技巧:

  • 标准线圈是"随动"的——能流变它就变
  • 如果同一个线圈在多个梯级中使用标准线圈,最后一个梯级的结果会覆盖前面的(危险! 反模式)
  • 建议每个标准线圈只在一个梯级中使用

3.2 取反线圈 (Negated Coil)

符号:

──(/)──

ASCII 表示:---(/)---

参数:

属性说明
符号--(/)--
写入条件能流导通时写 FALSE,断开时写 TRUE
SCL 等价&lt;变量&gt; := NOT &lt;能流条件&gt;;
典型用途反相输出控制

示例:

     bError                   bOK_Lamp
──┤ ├──────────────────────(/)──
// 错误时灯灭,正常时灯亮
// SCL: bOK_Lamp := NOT bError;

3.3 置位线圈 (Set / Latch)

符号:

──(S)──

ASCII 表示:---(S)---

参数:

属性说明
符号--(S)--
写入条件能流导通时置变量为 TRUE,断开时保持
SCL 等价IF &lt;能流条件&gt; THEN &lt;变量&gt; := 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 &lt;能流条件&gt; THEN &lt;变量&gt; := 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 │
└────────────┘

参数:

引脚类型说明
INBOOL 输入启动计时:TRUE 开始计时
PTTIME 输入预设延时时间
QBOOL 输出计时完成输出
ETTIME 输出已计时时间

时序图:

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 │
└────────────┘

参数:

引脚类型说明
INBOOL 输入FALSE 开始计时
PTTIME 输入断开延时时间
QBOOL 输出延时期间保持 TRUE
ETTIME 输出已计时时间

时序图:

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 │
└────────────┘

参数:

引脚类型说明
INBOOL 输入上升沿触发脉冲
PTTIME 输入脉冲宽度
QBOOL 输出脉冲输出
ETTIME 输出已计时时间

时序图:

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 │
└────────────┘

参数:

引脚类型说明
CUBOOL 输入上升沿计数+1
RBOOL 输入复位计数器(CV=0,Q=FALSE)
PVINT 输入预设值
QBOOL 输出CV >= PV 时 TRUE
CVINT 输出当前计数值

计数图:

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 │
└────────────┘

参数:

引脚类型说明
CDBOOL 输入上升沿计数-1
LDBOOL 输入加载预设值到 CV
PVINT 输入预设值
QBOOL 输出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 │
└───────────────┘

参数:

引脚类型说明
CUBOOL 输入上升沿计数+1
CDBOOL 输入上升沿计数-1
RBOOL 输入复位(CV=0,QU/QD=FALSE)
LDBOOL 输入加载 PV 到 CV
PVINT 输入预设值
QUBOOL 输出CV >= PV 时 TRUE
QDBOOL 输出CV <= 0 时 TRUE
CVINT 输出当前计数值

示例:库存管理

  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 = IN2IN1 = IN2
NE--[&lt;&gt;]--IN1 <> IN2IN1 &lt;&gt; IN2
GT--[&gt;]--IN1 > IN2IN1 &gt; IN2
LT--[&lt;]--IN1 < IN2IN1 &lt; IN2
GE--[&gt;=]--IN1 >= IN2IN1 &gt;= IN2
LE--[&lt;=]--IN1 <= IN2IN1 &lt;= 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减法2IN1 - IN2rDiff := IN1 - IN2
MUL乘法2+IN1 * IN2 * ...rProd := IN1 * IN2
DIV除法2IN1 / IN2rQuot := IN1 / IN2
MOD取模2IN1 MOD IN2iRem := 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√IN1SQRT(IN1)
SQR平方IN1IN1²IN1 * IN1
NEG取反IN1-IN1-IN1
LN自然对数IN1ln(IN1)LN(IN1)
LOG常用对数IN1log10(IN1)LOG(IN1)
EXP指数IN1e^IN1EXP(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 &lt;能流&gt; THEN &lt;OUT&gt; := &lt;IN&gt;; 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 │
└──────────────┘

参数:

引脚类型说明
ENABLEBOOL 输入上升沿触发传输
SRC任意数组源数组
DST任意数组目标数组
COUNTUDINT 输入传输元素数
DONEBOOL 输出传输完成
ERRBOOL 输出错误标志

示例:

  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 │
└───────────────┘

参数:

引脚类型说明
ENABLEBOOL 输入上升沿触发填充
VALUE任意类型填充值
DST数组目标数组
COUNTUDINT 输入填充元素数

示例:

  bInit      ┌─ FILL ───────┐    bDone
──┤P ├───────┤ ENABLE DONE ├───( )──
│ VALUE ERR │
0 ├──────────────┤
arBuffer ├──DST │
│ COUNT=100 │
└──────────────┘
// 将 arBuffer[0..99] 全部填充为 0

8.4 SWAP — 字节交换

符号:

  ┌─ SWAP ──┐
──┤ IN OUT├──
└─────────┘

参数:

引脚类型说明
INWORD/DWORD输入值
OUTWORD/DWORD字节交换后的值

示例:

  bSwap      ┌─ SWAP ──┐    wSwapped
──┤ ├────────┤ IN OUT├───
│ 16#1234 │
└──────────┘
// wSwapped = 16#3412 (高低字节交换)

9. 转换指令 (Convert)

转换指令用于数据类型之间的显式转换。

9.1 类型转换

符号:

  ┌─ INT_TO_REAL ─┐
──┤ IN OUT├──
└───────────────┘

常用转换:

功能说明
INT_TO_REALINT → REAL整数转浮点数
REAL_TO_INTREAL → INT浮点数转整数(截断)
BCD_TO_INTBCD → INTBCD 码转整数
INT_TO_BCDINT → BCD整数转 BCD 码
DINT_TO_REALDINT → REAL双整数转浮点数
REAL_TO_DINTREAL → DINT浮点数转双整数
WORD_TO_INTWORD → INT字转整数
INT_TO_WORDINT → 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 │
└───────────┘

参数:

引脚类型说明
INWORD/DWORD输入值
INDEXUINT 输入位索引(015 或 031)
OUTWORD/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任意整数类型输入值
NUINT 输入移位数
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)变量 = TRUEIF var THEN
--[/]--常闭触点 (NC)变量 = FALSEIF NOT var THEN
--[P]--上升沿检测FALSE→TRUE 瞬间R_TRIG(CLK:=v).Q
--[N]--下降沿检测TRUE→FALSE 瞬间F_TRIG(CLK:=v).Q
--[NOT]--取反输入断开时NOT condition
--[==]--等于比较IN1 = IN2IN1 = IN2
--[&lt;&gt;]--不等于比较IN1 <> IN2IN1 &lt;&gt; IN2
--[&gt;]--大于比较IN1 > IN2IN1 &gt; IN2
--[&lt;]--小于比较IN1 < IN2IN1 &lt; IN2
--[&gt;=]--大于等于IN1 >= IN2IN1 &gt;= IN2
--[&lt;=]--小于等于IN1 <= IN2IN1 &lt;= IN2

线圈速查

符号名称写入条件SCL 等价
--( )--标准线圈导通=TRUE, 断开=FALSEv := cond
--(/)--取反线圈导通=FALSE, 断开=TRUEv := NOT cond
--(S)--置位线圈导通=TRUE, 断开保持IF cond THEN v:=TRUE
--(R)--复位线圈导通=FALSE, 断开保持IF cond THEN v:=FALSE
--(M)--保持线圈同标准线圈,断电保持v := cond (RETAIN)

定时器速查

类型触发Q 行为复位条件
TONIN=TRUE 开始计时延时后 Q=TRUEIN=FALSE 时 ET 清零
TOFIN→FALSE 开始计时IN=TRUE 时 Q 立即 TRUE计时结束 Q=FALSE
TPIN 上升沿触发Q 输出固定宽度脉冲PT 到期后 Q=FALSE

计数器速查

类型计数方向复位输出条件
CTU递增 (CU)R 复位CV >= PV 时 Q=TRUE
CTD递减 (CD)LD 加载 PVCV <= 0 时 Q=TRUE
CTUD双向 (CU+CD)R 复位 + LD 加载QU: CV>=PV; QD: CV<=0

数学运算速查

输入输出说明
ADD2+ 个IN1 + IN2 + ...
SUB2 个IN1 - IN2
MUL2+ 个IN1 * IN2 * ...
DIV2 个IN1 / IN2
MOD2 个余数IN1 MOD IN2
ABS1 个绝对值|IN|
SQRT1 个平方根√IN (IN >= 0)
SQR1 个平方IN²
NEG1 个取反-IN
SIN1 个正弦sin(IN) 弧度
COS1 个余弦cos(IN) 弧度
TAN1 个正切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

性能优化建议

  1. 梯级数量控制:单个 POU 梯级不超过 50 级,超过则拆分子程序
  2. 减少分支嵌套:分支深度不超过 4 层,过深影响扫描效率
  3. 避免空梯级:空梯级浪费扫描时间,及时清理
  4. 使用 MOVE 代替多个线圈:需要同时赋多个值的场景,考虑用 MOVE 块一次赋值
  5. 定时器 PT 不要频繁修改:PT 值变化需重新初始化定时器
  6. 高速任务用 SCL:1ms 以下周期任务建议用 SCL 替代 LAD

常见反模式

反模式问题正确做法
线圈双向驱动同一线圈在多个梯级赋值合并到一个梯级或用 S/R
空线圈悬空线圈未绑定变量确认每个线圈都有有效变量
触点直接连母线左母线直连右母线,短路加中间变量或空线圈
定时器嵌套过深定时器输出再驱动定时器用顺序逻辑替代嵌套
分支未闭合分支有头无尾确保分支汇合到公共路径
跳转滥用JMP 满天飞,逻辑不连续用 S/R 顺序控制替代
变量类型混用INT 直接连 BOOL 输入用比较块转换

相关文档