TIA Portal (博图) 中 SCL 语言 REPEAT_UNTIL循环语句的用法介绍及案例
博图 SCL 编程利器:深入理解 REPEAT_UNTIL 循环
在西门子 TIA Portal 的 SCL (Structured Control Language) 编程环境中,循环结构是处理重复性任务的核心。除了常见的FOR 和 WHILE 循环,REPEAT_UNTIL循环提供了一种独特的“先执行,后判断”的控制流方式,特别适用于那些至少需要执行一次循环体的场景。本文将详细介绍 `REPEAT_UNTIL` 的语法、执行逻辑、与 `WHILE` 的区别,并通过实际案例展示其应用。
一、.REPEAT_UNTIL语句语法
二、.执行逻辑详解
核心特点:先执行,后判断。循环体至少执行一次。
三.、REPEAT_UNTIL vs WHILE:关键区别
理解 REPEAT_UNTIL 与 WHILE 循环的区别至关重要:
选择建议:
如果任务无论如何都需要先做一次,然后再根据结果决定是否继续做,选择REPEAT_UNTIL。
如果任务需要先检查条件是否允许做,允许才做,选择 WHILE。
四. 应用案例
案例 1:简单累加 (演示基本用法)
需求:计算从 1 开始累加,直到总和大于等于 100 为止,记录累加的次数和最终的总和。
FUNCTION_BLOCK FB_REPEAT_UNTIL_Demo
VAR
iCounter : Int := 0; // 循环计数器 (也代表累加的数字)
iSum : Int := 0; // 累加和
iLoopCount : Int := 0; // 记录循环执行次数
END_VAR
// 使用 REPEAT_UNTIL 循环
REPEAT
iCounter := iCounter + 1; // 计数器递增 (当前要加的数字)
iSum := iSum + iCounter; // 累加当前数字
iLoopCount := iLoopCount + 1; // 记录循环次数
UNTIL iSum >= 100; // 条件:当总和 >= 100 时停止循环
// 循环结束后,iCounter, iSum, iLoopCount 即包含所需结果
解释:
1. 进入循环前,所有变量初始化为 0。
2. 第一次循环 (`iLoopCount=1`):`iCounter` 变为 1,`iSum` 变为 1。
3. 检查条件 `iSum >= 100` (1 >= 100?) -> `FALSE` -> 继续循环。
4. 第二次循环:`iCounter=2`, `iSum=1+2=3` -> 条件 `FALSE` -> 继续。
5. ... (持续累加) ...
6. 当 `iSum` 累加到某个值 (例如 91),加上 `iCounter=14` 后,`iSum=105`。
7. 执行完这次循环体 (`iLoopCount=14`) 后,检查条件 `105 >= 100` -> `TRUE` -> **退出循环**。
8. 最终 `iCounter=14`, `iSum=105`, `iLoopCount=14`。
关键点:即使初始 `iSum=0` 已经满足 `iSum >= 100`? (`FALSE`),循环体也执行了一次才检查条件。这个例子中初始不满足,所以执行了多次,但逻辑保证了至少执行一次。
案例 2:读取设备状态直到成功或超时
需求: 控制一台设备启动后,需要反复读取其状态寄存器,直到状态变为“运行就绪”(`bReady = TRUE`)或者尝试次数超过最大限制(`iMaxTries`)。如果超时仍未就绪,则报错。
FUNCTION_BLOCK FB_DeviceStartMonitor
VAR
bDeviceReady : BOOL; // 输入:设备状态信号 (来自硬件或模拟)
iMaxTries : INT := 10; // 常量:最大尝试次数
iCurrentTry : INT := 0; // 当前尝试次数
bStartSuccess : BOOL; // 输出:启动是否成功
bTimeout : BOOL; // 输出:是否超时
tDelay : TIME := T#500ms; // 常量:每次读取间隔时间
END_VAR
// 初始化监控变量
iCurrentTry := 0;
bStartSuccess := FALSE;
bTimeout := FALSE;
// 使用 REPEAT_UNTIL 监控设备状态
REPEAT
iCurrentTry := iCurrentTry + 1; // 增加尝试计数
// 模拟或实际读取设备状态 (这里假设bDeviceReady是外部更新的)
// ... (可能需要等待或处理) ...
WAIT TIME := tDelay; // 等待一段时间再读 (避免过于频繁查询, 实际SCL中需注意WAIT使用场景)
UNTIL bDeviceReady OR (iCurrentTry >= iMaxTries); // 条件:设备就绪 OR 达到最大次数
// 根据退出条件判断结果
IF bDeviceReady THEN
bStartSuccess := TRUE; // 设备成功就绪
bTimeout := FALSE;
ELSE
bStartSuccess := FALSE; // 超时未就绪
bTimeout := TRUE;
// 可以在这里触发报警或其他错误处理
END_IF;
解释:
1. 启动设备后,调用此功能块。
2. 进入 REPEAT循环,立即执行第一次状态读取 (iCurrentTry 变为 1)。
3. 等待 tDelay(500ms)。
4. 检查条件:bDeviceReady OR (iCurrentTry >= iMaxTries)。
* 如果设备已就绪 (bDeviceReady=TRUE),条件为 TRUE -> 退出循环,设置启动成功。
* 如果未就绪且尝试次数 < iMaxTries,条件为 FALSE-> 继续循环。
5. 重复步骤 2-4。
6. 要么在达到iMaxTries之前设备就绪 (bDeviceReady在循环体内变为 TRUE,下次检查条件时退出),
7. 要么执行到第 iMaxTries次循环后,检查条件 (10 >= 10) = TRUE`-> 退出循环,报告超时错误。
关键点:这个场景必须至少读取一次设备状态,无论设备是否已经就绪。REPEAT_UNTIL 完美契合这个需求。使用 `WHILE` 也可以实现,但需要更复杂的初始条件设置或额外的读取语句。
五.、重要注意事项与最佳实践
1. 避免死循环: 确保 UNTIL 的条件在有限次数的迭代后最终能够变为 TRUE。如果条件永远无法满足,程序将陷入死循环,导致 PLC 看门狗超时或任务周期超时,引发严重故障。始终考虑设置最大循环次数或超时机制 (如案例2所示)。
2. 循环体内修改条件: 循环体内的代码必须有能力改变 UNTIL 条件中涉及的变量值,否则循环可能永远不会退出或立即退出。
3. 性能考量: 循环体执行时间不能过长,否则会影响 PLC 的整体扫描周期时间。对于耗时操作(如大量数据处理、复杂计算、通信等待),应考虑拆分任务、使用后台任务或状态机编程。
4. 变量作用域:在循环体内声明的变量 (VAR_TEMP) 只在当前循环迭代中有效。需要在循环间保持值的变量必须在循环体外声明 (VAR, VAR_INST 等)。
5. EXIT 语句: SCL 支持在循环体内部使用 EXIT 语句强制立即退出当前循环。这提供了一种在特定点提前退出的灵活性。
6. 可读性:对于复杂的循环逻辑,添加清晰的注释说明循环的目的、退出条件和关键步骤。
六.、总结
REPEAT_UNTIL 循环是 TIA Portal SCL 编程中一个强大的工具,它保证了循环体代码至少被执行一次,然后根据条件决定是否继续。这种“先执行,后判断”的模式非常适合那些初始化操作、状态读取、必须尝试至少一次的任务。
理解和正确应用 REPEAT_UNTIL,并与 WHILE和 FOR 循环区分开,将使你的 SCL 代码逻辑更清晰、更健壮,更能满足各种工业自动化控制的需求。记住关键的**避免死循环**原则,并在实际项目中灵活运用它吧!
希望这篇介绍和案例能帮助你更好地掌握博图中 REPEAT_UNTIL` 语句的用法!