ST怎么写条件判断赋值:IF Temp > 100 THEN Alarm := TRUE; ELSE Alarm := FALSE; END_IF;

发布于 2026-03-15 02:26:56 · 浏览 2 次 · 评论 0 条

在结构化文本(Structured Text,ST)编程中,条件判断赋值是电气自动化控制逻辑最基础、最频繁使用的语法结构。它直接对应PLC(可编程逻辑控制器)对物理过程的实时响应——比如温度超限报警、液位过高停泵、电机过载切断电源等。你看到的这行代码:

IF Temp > 100 THEN Alarm := TRUE; ELSE Alarm := FALSE; END_IF;

表面只是一条赋值语句,背后却承载着工业现场的安全边界、设备寿命保障和系统可靠性。本文不讲抽象理论,只聚焦“怎么写对”“为什么这么写”“常见错在哪”“如何扩展更实用”,手把手带你写出稳定、可读、易维护的ST条件判断逻辑。


一、先拆解:这条语句每个字符都干什么用?

我们逐字符解析原始语句,不跳步:

IF —— 关键字,表示条件判断块开始。必须大写(IEC 61131-3标准规定ST关键字不区分大小写,但行业惯例全大写以提高可读性,且部分PLC编辑器(如TIA Portal、Codesys)默认高亮大写形式)。

Temp > 100 —— 布尔表达式,即“判断条件”。这里Temp是变量名(通常为REALINT类型),>是关系运算符,100是字面常量。整个表达式运算结果只能是TRUEFALSE

THEN —— 关键字,紧接在条件后,表示“当条件成立时,执行以下语句”。

Alarm := TRUE; —— 赋值语句。:=是ST中唯一合法的赋值运算符(注意:不是==在ST中仅用于相等比较)。Alarm是布尔型变量(BOOL),TRUE是预定义布尔常量。分号;是语句结束符,不可省略

ELSE —— 关键字,表示“当条件不成立时,执行以下语句”。

Alarm := FALSE; —— 同上,给同一变量赋相反值。

END_IF; —— 关键字组合,表示整个IF块结束。必须带分号,且END_IF之间无空格(写作END_IF,不是END IFEND-IF)。

✅ 正确完整写法(含空格与分号规范):

IF Temp > 100 THEN
  Alarm := TRUE;
ELSE
  Alarm := FALSE;
END_IF;

注意:虽然单行写法IF Temp > 100 THEN Alarm := TRUE; ELSE Alarm := FALSE; END_IF;语法合法,但强烈建议分行缩进。原因有三:

  1. PLC调试时,编辑器按行报错,单行长句出错定位困难;
  2. 多个ELSEIF分支叠加时,单行无法阅读;
  3. 符合IEC 61131-3推荐的代码风格,便于团队协作与审核。

二、必须避开的5个典型错误(真实工程中高频发生)

错误1:混淆赋值:=与比较=

❌ 错误写法:IF Temp > 100 THEN Alarm = TRUE; END_IF;
→ 编译器报错:Syntax error: expected ':=' but found '='
✅ 修正:所有赋值必须用:=;比较两个值是否相等,才用=(如IF State = START THEN ...)。

错误2:忘记分号;

❌ 错误写法:

IF Temp > 100 THEN  
  Alarm := TRUE  
ELSE  
  Alarm := FALSE  
END_IF

→ 多数编辑器(如Unity Pro、PLCnext Engineer)会提示Missing semicolon,编译失败。
✅ 修正:每个语句末尾、END_IF后都必须有;

错误3:变量类型不匹配

假设Temp定义为REAL(浮点数),而误写成IF Temp > 100.0 THEN ...看似合理,但若Temp实为INT,某些PLC(如旧版Modicon M340)可能隐式转换失败或触发警告。更危险的是:
IF Temp > 100 THEN Alarm := 1; END_IF;
AlarmBOOL,但1是整数,非标准布尔字面量。部分平台允许,但违反IEC 61131-3,跨平台移植必出错。
✅ 修正:布尔变量只赋TRUEFALSE;数值变量用对应类型常量(100用于INT100.0用于REAL)。

错误4:嵌套IF缺少END_IF配对

❌ 错误写法:

IF Mode = AUTO THEN  
  IF Temp > 100 THEN  
    Alarm := TRUE;  
  ELSE  
    Alarm := FALSE;  
END_IF;  ← 这里只闭合了内层IF,外层IF没有END_IF!

→ 编译报错:Expected 'END_IF'Unexpected token
✅ 修正:每层IF必须有且仅有一个对应END_IF,缩进对齐是自查关键。

错误5:条件表达式含未初始化变量

Temp变量声明了但未在程序其他位置赋初值,首次扫描时其值为随机内存内容(如327670.0)。
→ 可能导致Alarm初始状态为TRUE,设备一上电就误报警。
✅ 修正:在INIT段(初始化段)或主程序首行显式初始化:

Temp := 0.0;   // 若为REAL  
Alarm := FALSE; // 显式置初始安全态

三、从“能运行”到“该这样写”:4种生产级优化写法

写法1:用ELSIF处理多区间判断(替代嵌套IF)

场景:温度分三级报警(高温停机、中温预警、正常)
❌ 嵌套写法(难读、易漏END_IF):

IF Temp > 150 THEN  
  Status := SHUTDOWN;  
ELSE  
  IF Temp > 100 THEN  
    Status := WARNING;  
  ELSE  
    Status := NORMAL;  
  END_IF;  
END_IF;

✅ 推荐写法(清晰、扁平、易扩展):

IF Temp > 150 THEN  
  Status := SHUTDOWN;  
ELSIF Temp > 100 THEN  
  Status := WARNING;  
ELSE  
  Status := NORMAL;  
END_IF;

⚠️ 注意:ELSIF是一个单词(无空格),不是ELSE IF。后者会被解释为ELSE后跟一个新IF块,逻辑不同。

写法2:单行条件赋值(简洁版,适合简单二值逻辑)

IEC 61131-3支持三元操作符风格的函数式赋值:

Alarm := (Temp > 100);  // 直接将布尔表达式结果赋给BOOL变量

✅ 优势:1行解决,无分支开销,CPU扫描周期更短;
⚠️ 限制:仅适用于“条件结果直接等于目标变量值”的场景(即不需要ELSE分支做反向赋值)。

衍生技巧:可嵌套逻辑运算
Alarm := (Temp > 100) AND (Pump_Running = TRUE);

写法3:用CASE替代长链ELSIF(当判断离散值时)

场景:根据ErrorCode(INT类型)设置不同报警文本
❌ 长ELSIF链:

IF ErrorCode = 1 THEN  
  Msg := 'SENSOR_FAULT';  
ELSIF ErrorCode = 2 THEN  
  Msg := 'COMM_LOST';  
ELSIF ErrorCode = 3 THEN  
  Msg := 'OVERLOAD';  
ELSE  
  Msg := 'UNKNOWN';  
END_IF;

✅ 更优写法(CASE结构,CPU执行效率更高):

CASE ErrorCode OF  
  1: Msg := 'SENSOR_FAULT';  
  2: Msg := 'COMM_LOST';  
  3: Msg := 'OVERLOAD';  
  ELSE Msg := 'UNKNOWN';  
END_CASE;

CASE要求判断变量为整数或枚举类型;每个分支用冒号:结尾;ELSE处理未列情况。

写法4:封装为函数块(FB),实现逻辑复用

当同一判断逻辑在多个地方使用(如10个温度点都要超温报警),重复写IF语句会导致:修改一处要改10处、易遗漏、版本不一致。
✅ 正确做法:新建函数块FB_TempAlarm,接口如下:
| 参数名 | 类型 | 方向 | 说明 |
| :--- | :--- | :--- | :--- |
| InputTemp | REAL | INPUT | 实时温度值 |
| Threshold | REAL | INPUT | 报警阈值(可配置) |
| AlarmOut | BOOL | OUTPUT | 报警输出 |

函数块内部ST代码:

AlarmOut := (InputTemp > Threshold);

调用时只需:

TempAlarm_1(InputTemp := T_Tank1, Threshold := 95.0, AlarmOut => ALM_Tank1);  
TempAlarm_2(InputTemp := T_Pump, Threshold := 80.0, AlarmOut => ALM_Pump);

→ 阈值集中配置,逻辑统一升级,故障隔离性强。


四、关键安全原则:为什么“ELSE分支不能省略”

初学者常写:

IF Temp > 100 THEN  
  Alarm := TRUE;  
END_IF;  // ❌ 省略ELSE

表面看功能相同(温度≤100时Alarm保持原值),但存在严重隐患:

  • Alarm初始值为TRUE(因未初始化或上次故障遗留),则温度回落至99℃时,Alarm仍为TRUE,无法自动复位;
  • 安全标准(如IEC 61508、ISO 13849)明确要求:安全相关输出必须有确定的默认状态,不能依赖“历史值”。

✅ 正确做法:任何安全输出变量,IF结构必须覆盖所有逻辑路径
更进一步,采用“故障安全设计”:

IF (Temp > 100) AND (System_Ready = TRUE) THEN  
  Alarm := TRUE;  
ELSE  
  Alarm := FALSE;  // 所有非报警条件,强制清零
END_IF;

→ 即使System_ReadyFALSE(如急停按下),也确保AlarmFALSE,避免误信号干扰上位机。


五、调试实战:3步快速定位IF逻辑问题

  1. 在线监控变量值:在PLC编辑器中,将TempAlarmSystem_Ready等变量加入在线监视表,实时观察值变化与IF执行是否同步。
  2. 插入临时测试点:在THENELSE分支内,各加一行TestFlag := TRUE;TestFlag为BOOL型全局变量),通过监视TestFlag确认哪条路径被触发。
  3. 模拟边界值:手动修改Temp99.9100.0100.1,验证阈值动作点是否精准(注意浮点精度:100.0100REAL比较中等价,但100.0001 > 100.0成立)。

六、扩展:结合定时器实现延时确认报警(防抖)

真实工业场景中,传感器可能瞬时干扰导致误触发。需增加“持续超限3秒才报警”逻辑:

// 声明静态变量(保留在FB内,断电不丢失需加RETAIN)
VAR  
  tON_100: TON;     // IEC标准定时器功能块  
  bConfirmed: BOOL;  
END_VAR  

// 主逻辑  
IF Temp > 100 THEN  
  tON_100(IN := TRUE, PT := T#3S);  // 启动3秒定时器  
  bConfirmed := tON_100.Q;          // Q为定时完成标志  
ELSE  
  tON_100(IN := FALSE);             // 复位定时器  
  bConfirmed := FALSE;              // 清除确认标志  
END_IF;  

Alarm := bConfirmed;  // 报警仅在确认后置位

→ 此写法将条件判断与时间逻辑解耦,符合模块化设计思想。


七、终极检查清单(每次写完IF语句前必核对)

检查项 是/否 说明
IF/THEN/ELSIF/ELSE/END_IF 关键字全部大写? 提升可读性与兼容性
每个语句末尾都有分号; 包括END_IF;
赋值一律用:=,比较一律用= 混用必报错
所有变量已声明且类型匹配? 特别检查BOOL变量只赋TRUE/FALSE
ELSE分支是否存在?安全输出是否强制设默认值? 防止状态残留
多层嵌套时,缩进是否对齐?END_IF数量是否与IF数量相等? 用编辑器“折叠代码”功能一键验证
是否有未初始化的输入变量参与条件判断? 初始化应在程序入口处完成

IF Temp > 100 THEN Alarm := TRUE; ELSE Alarm := FALSE; END_IF; 这行代码,不是语法练习,而是工程师对产线安全的一次郑重承诺。写对它,靠的不是记忆符号,而是理解每一个分号背后的执行顺序、每一个布尔值所代表的物理世界状态、每一次END_IF所封闭的责任边界。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文