当前位置: 首页 > ai >正文

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` 语句的用法!

http://www.xdnf.cn/news/14464.html

相关文章:

  • 资源占用多,Linux 系统中如何降低 CPU 资源消耗并提升利用率?
  • CentOS 7 虚拟机网络配置异常 典型问题:启动了NetworkManager但是network无法启动
  • 03.【C语言学习笔记】分支和循环
  • 网络层协议 IP 协议介绍 -- IP 协议,网段划分,私有 IP 和 公网 IP,路由
  • 设计模式笔记_创建型_单例模式
  • 【图像处理入门】9. 基础项目实战:从去噪到图像加密
  • 接口适配器模式实现令牌桶算法和漏桶算法
  • 加密、加签、摘要算法对比
  • 自然语言处理【NLP】—— CBOW模型
  • 浅谈快排的退化与优化
  • 鼠标报告描述符与对应的数据结构体
  • 实现汽车焊装线设备互联:DeviceNet与Modbus TCP协议转换网关
  • Debian 编译安装 ruby3.2
  • stm32使用定时器PWM
  • Linux编程:4、进程通信-管道(匿名管道)
  • 二手商城系统+SpringBoot + Vue (前后端分离)
  • 通用embedding模型和通用reranker模型,观测调研
  • 嵌入式学习笔记C语言阶段--17共用体和枚举
  • LG P4278 带插入区间K小值 Solution
  • SCADA|KingSCADA通过组合框选择修改变量的值
  • JS进阶 Day04
  • 2GT 环形闭口闭环同步带一种具有特定齿形和结构的传动带
  • MotleyCrew ——抛弃dify、coze,手动搭建多agent工作流
  • Cangejie Magic智谱AI文生图API实战详解
  • 洛谷 排队接水 贪心
  • 2025CVPR最佳论文系列
  • AI 产品设计头脑风暴
  • Leetcode 3583. Count Special Triplets
  • 【python深度学习】Day 54 Inception网络及其思考
  • 深入理解IOC与DI