返回
SCL PLC 编程教程第四篇 条件判断:IF、ELSIF、ELSE、CASE 怎么写才清楚


很多工程师第一次学 SCL 时,会觉得判断语句并不陌生。
因为在梯形图里,我们平时其实也一直在做判断:

按钮按下没有
急停断开没有
故障存在没有
自动模式有没有选中
温度是否超过上限
当前步骤是不是第 10 步
电机反馈有没有回来

这些本质上全是判断。

只不过在梯形图里,判断通常是通过触点串联、并联、比较块等方式表现出来;而到了 SCL 里,这些逻辑开始用文本结构来表达。

也就是说,以前你是“画判断”,现在你要学会“写判断”。

很多人觉得 IF、CASE 看起来简单,但真正写项目时又常常会出现这些问题:

条件越写越长,自己都看晕了
多个条件的优先级理不清
嵌套太深,后面维护很痛苦
明明逻辑意思差不多,却总觉得程序不清爽
什么时候用 IF,什么时候用 CASE,心里没底
结果虽然能运行,但别人一看就头大

这说明,条件判断不是只会语法就够了。
真正重要的是:你能不能把判断写得清楚、稳、符合工程习惯。

这一篇我们就把这个问题讲透。

一、先把最核心的一句话记住:条件判断不是在“写语法”,而是在“表达决策逻辑”

初学者最容易有一个误区:
把 IF、ELSIF、ELSE、CASE 当成一堆语法关键字在记。

但其实它们的本质不是语法,而是程序在做决策的方式。

比如你在现场调试一台设备时,脑子里经常会这样想:

如果急停按下了,就必须停机。
如果没有急停,但有故障,也不能启动。
如果没有故障,而且在自动模式下,才允许启动。
如果当前是手动模式,就按另外一套逻辑走。

这就是典型的决策结构。

SCL 的条件判断,只是把这种思维变成了程序语言。

所以你学这一篇时,不要只是盯着:

IF
THEN
ELSE
END_IF
CASE
OF

你更应该盯着这个问题:

我这段逻辑,到底是在做什么决策?

一旦这个问题想清楚,语句就不会乱。

二、IF 到底是什么

IF 是最基础、也最常用的条件判断结构。
它最适合处理这种场景:

当某个条件成立时,执行某段逻辑。

最基础的写法是:

IF 条件 THEN
    语句;
END_IF;

例如:

IF StartPB THEN
    MotorRun := TRUE;
END_IF;

意思很简单:

如果启动按钮按下,那么让电机运行。

这就是最基本的 IF 结构。

从这里你要先建立一个感觉:
IF 的本质不是“写一段代码”,而是“先判断,再决定是否执行”。

三、IF 后面的“条件”到底可以是什么

这是很多初学者一开始容易模糊的地方。

很多人以为 IF 后面只能写一个布尔变量。
其实不是。IF 后面可以是任何最终结果为 TRUE 或 FALSE 的表达式。

例如下面这些都可以:

1. 直接判断一个布尔变量
IF AutoMode THEN
    RunPermit := TRUE;
END_IF;

意思是:如果当前是自动模式,那么允许运行。

2. 多个布尔条件组合
IF AutoMode AND NOT Fault AND SafetyOK THEN
    RunPermit := TRUE;
END_IF;

意思是:只有自动模式成立、没有故障、安全条件满足,才允许运行。

3. 数值比较
IF Temperature > 80.0 THEN
    TempHighAlarm := TRUE;
END_IF;

意思是:如果温度大于 80,就触发高温报警。

4. 步骤号判断
IF StepNo = 10 THEN
    ClampCmd := TRUE;
END_IF;

意思是:如果当前步骤是 10,就执行夹紧动作。

5. 组合比较条件
IF Pressure > 0.6 AND ValveOpenFB THEN
    ProcessReady := TRUE;
END_IF;

所以你一定要明白:

IF 后面不是只能跟一个变量,而是可以跟一个完整的逻辑表达式。

这在工程里非常重要,因为 PLC 程序里很少只有单一条件。

四、THEN 到底表示什么

THEN 可以理解成“那么”。

它把一个条件和一组执行动作连接起来。

也就是说:

IF 后面是“前提”
THEN 后面是“前提成立后要做的事”

例如:

IF Fault THEN
    MotorRun := FALSE;
    AlarmLamp := TRUE;
END_IF;

这里的意思是:

如果故障存在,那么:
电机停止;
报警灯点亮。

你可以发现,THEN 后面不一定只有一行语句。
只要属于这个条件成立时要执行的内容,都可以放在这个结构里。

这也是为什么缩进很重要。
因为缩进清楚了,你一眼就知道哪些语句属于这个判断块。

五、ELSE 是什么,什么时候该用

ELSE 的意思是“否则”。

它适合用在这种场景:

当条件成立时做一种处理,不成立时做另一种处理。

典型写法:

IF 条件 THEN
    条件成立时执行;
ELSE
    条件不成立时执行;
END_IF;

比如:

IF TankLevel > 80.0 THEN
    PumpRun := FALSE;
ELSE
    PumpRun := TRUE;
END_IF;

意思是:

如果液位大于 80,那么水泵停止;
否则,水泵运行。

这个例子虽然简单,但很能说明 ELSE 的作用。
它不是附属品,而是告诉程序:

这个判断不是只有“成立时做什么”,还包括“不成立时怎么办”。

很多初学者常常写 IF,但不敢写 ELSE。
其实如果逻辑本身天然有两面,那就应该大胆用 ELSE,这样程序反而更完整。

六、ELSIF 是什么,为什么它很适合 PLC 程序

ELSIF 可以理解成“否则如果”。

它适合处理这种情况:

条件不是两种,而是有好几层分支,并且有先后优先级。

例如:

IF Fault THEN
    MotorRun := FALSE;
ELSIF StopPB THEN
    MotorRun := FALSE;
ELSIF StartPB THEN
    MotorRun := TRUE;
END_IF;

这段程序的意思是:

如果故障存在,停机;
否则如果停止按钮按下,停机;
否则如果启动按钮按下,运行。

这就是典型的多分支判断。

在 PLC 项目里,ELSIF 非常常用,因为很多实际逻辑本来就不是简单二选一,而是这种结构:

先判断最高优先级的停机条件;
再判断普通停止条件;
再判断启动条件;
再判断其他补充条件。

你可以把 ELSIF 理解成一层一层往下筛选。
程序会从上往下看,哪个条件先成立,就执行哪个分支,然后结束这个判断结构。

这一点特别重要:

ELSIF 结构中,一旦前面的条件成立,后面的分支就不会再继续执行。

所以分支顺序本身就带有“优先级”意义。

七、PLC 工程里,为什么条件顺序特别重要

这点必须重点讲。

在日常语言里,我们可能觉得条件顺序影响不大。
但在 PLC 程序里,顺序常常决定逻辑结果。

比如下面这个例子:

IF StartPB THEN
    MotorRun := TRUE;
ELSIF Fault THEN
    MotorRun := FALSE;
END_IF;

表面上看,好像也能工作。
但如果启动按钮按下和故障同时存在,会怎样?

程序会先看到 StartPB 成立,于是直接让电机运行;
后面的 Fault 分支根本不会执行。

这显然不合理。

因为工程上通常应该是:

故障优先级高于启动命令。

所以更合理的写法应该是:

IF Fault THEN
    MotorRun := FALSE;
ELSIF StartPB THEN
    MotorRun := TRUE;
END_IF;

你看,语法变化不大,但逻辑优先级完全不同。

所以你以后写条件判断时,要反复问自己一个问题:

这些条件里,谁的优先级最高?

一般来说,在 PLC 项目中,优先级往往会先考虑这些:

急停
安全链断开
严重故障
停止命令
复位条件
启动命令
普通附加条件

也就是说,很多程序并不是“谁成立都行”,而是必须先处理最重要、最危险、最强制的条件。

这就是为什么条件判断不仅是语法问题,更是控制思路问题。

八、一个 IF 里可以写多少语句

理论上可以写很多。
但工程上并不建议无限堆积。

例如:

IF AutoMode AND SafetyOK AND NOT Fault THEN
    MotorRun := TRUE;
    ValveOpen := TRUE;
    Buzzer := FALSE;
    RunLamp := TRUE;
    StartCounter := StartCounter + 1;
END_IF;

这段程序语法上没有问题。
但当 IF 里面的动作越来越多时,你就要开始警惕:

是不是这个判断块承担了太多职责。

因为一个好的程序,不只是能运行,还应该:

容易理解
容易调试
容易局部修改
出问题时容易定位

如果某个 IF 块里塞了十几行、几十行不同性质的操作,那后面很容易变得难维护。

所以从工程习惯来说,IF 里面可以放多句,但最好仍保持单一逻辑主题。
比如:

这一段只处理运行命令
那一段只处理报警状态
另一段只处理步骤切换

而不是全部混在一个 IF 里。

九、什么时候只用 IF,不用 ELSE

这个情况很常见。

例如:

IF ResetPB THEN
    AlarmLatch := FALSE;
END_IF;

意思是:

如果复位按钮按下,就清除报警锁存。

这里就没必要写 ELSE。
因为“不按下按钮”时,本来就是什么都不做。

也就是说,如果你的逻辑只是:

条件成立时执行某动作,不成立时保持原样或无需处理,

那么只用 IF 就够了。

不要为了“结构完整”强行加 ELSE。
否则程序会显得累赘。

十、什么时候必须考虑 ELSE

如果一个结果必须明确地在两种状态之间切换,那就要考虑 ELSE。

比如:

IF AutoMode THEN
    ModeLamp := TRUE;
ELSE
    ModeLamp := FALSE;
END_IF;

这里如果你只写:

IF AutoMode THEN
    ModeLamp := TRUE;
END_IF;

那自动模式退出后,灯未必会自动灭掉,因为你没有明确写“不成立时怎么办”。

所以你可以这样理解:

凡是结果需要被明确刷新为两种状态之一时,ELSE 往往很重要。

常见场景包括:

灯亮或灭
允许或禁止
阀门开或关
模式标志置位或清零
状态输出为真或假
十一、初学者最容易犯的 IF 错误之一:把“判断”和“赋值”混掉

这一点前一篇提过,但这里要再强调。

看这两种写法:

IF MotorRun = TRUE THEN



MotorRun := TRUE;

第一句是判断。
第二句是赋值。

很多初学者写条件判断时,脑子里明明是“如果故障存在”,结果手上写成了“Fault := TRUE”,这就不是判断了,而是在改变量值。

所以以后写 IF 时,先提醒自己一句:

IF 后面是判断条件,不是给变量赋值。

十二、复杂条件到底要不要一行写完

这个问题在工程里很现实。

比如一个启动许可条件,可能要考虑:

自动模式
没有急停
没有总故障
安全门关闭
上游允许
下游允许
气压正常
原点已回
当前不在报警确认状态

如果全部一行写完,可能会变成这样:

IF AutoMode AND NOT EStop AND NOT GlobalFault AND SafetyDoorClosed AND UpstreamReady AND DownstreamReady AND AirPressureOK AND HomeDone AND NOT AlarmAckBusy THEN
    StartPermit := TRUE;
END_IF;

语法上没问题,但可读性不太好。
特别是后期调试时,别人一眼不容易看出到底是哪个条件没满足。

更好的工程写法往往有两种思路。

第一种:拆成中间变量
StartPermit := AutoMode
               AND NOT EStop
               AND NOT GlobalFault
               AND SafetyDoorClosed
               AND UpstreamReady
               AND DownstreamReady
               AND AirPressureOK
               AND HomeDone
               AND NOT AlarmAckBusy;

然后再使用:

IF StartPermit THEN
    MotorRun := TRUE;
END_IF;

这样逻辑会清晰很多。

第二种:分层判断
IF AutoMode THEN
    IF NOT EStop AND NOT GlobalFault THEN
        IF SafetyDoorClosed AND AirPressureOK THEN
            IF UpstreamReady AND DownstreamReady THEN
                StartPermit := TRUE;
            END_IF;
        END_IF;
    END_IF;
END_IF;

这种方式也能写,但嵌套层次会比较深。
如果条件过多,阅读压力会变大。

所以工程上通常更推荐第一种:
复杂条件尽量提炼成有意义的中间变量。

这样做有几个好处:

逻辑更清楚
后续监控更方便
哪个条件不满足更容易查
程序整体更整洁
十三、嵌套 IF 能不能用

当然能用。
而且在很多 PLC 场景下是正常的。

例如:

IF AutoMode THEN
    IF StartPB THEN
        IF NOT Fault THEN
            MotorRun := TRUE;
        END_IF;
    END_IF;
END_IF;

意思是:

如果在自动模式下,
并且启动按钮按下,
并且没有故障,
那么电机运行。

语法没有问题,逻辑也正确。

但嵌套 IF 有一个现实问题:
层数一多,就容易难看、难查、难改。

比如你嵌套到四层、五层、六层,后面再加 ELSE、ELSIF,很容易把自己绕进去。

所以对嵌套 IF 的工程建议是:

可以用,但不要滥用。
只要能通过中间变量或更清楚的结构来减少层数,就尽量减少。

一句实在话:

不是嵌套 IF 不能写,而是嵌套太深后,维护成本会越来越高。

十四、CASE 是什么,它和 IF 有什么不同

CASE 也是条件分支结构,但它和 IF 的思路不太一样。

IF 更像是在问:

如果这样呢?
否则如果那样呢?
否则如果再那样呢?

而 CASE 更像是在问:

这个变量当前等于哪一种状态?

它的典型写法是:

CASE 变量 OF
    值1:
        语句;
    值2:
        语句;
    值3:
        语句;
END_CASE;

例如:

CASE StepNo OF
    0:
        MotorRun := FALSE;

    10:
        ClampCmd := TRUE;

    20:
        FeedCmd := TRUE;
END_CASE;

意思是:

当步骤号是 0 时,停机;
当步骤号是 10 时,执行夹紧;
当步骤号是 20 时,执行送料。

你一眼就能感觉到,CASE 特别适合这种“一个变量对应多个状态”的场景。

十五、什么时候更适合用 IF,什么时候更适合用 CASE

这是非常关键的工程判断。

更适合用 IF 的场景

IF 适合处理“条件逻辑判断”。

比如:

是否有故障
是否按下启动按钮
是否大于某个温度
是否满足一组运行许可条件
是否在自动模式且安全条件成立

也就是说,只要你的逻辑重点在于“判断某个条件是否成立”,那通常更适合 IF。

更适合用 CASE 的场景

CASE 适合处理“一个变量有多个明确状态”的场景。

比如:

步骤号 StepNo
模式号 ModeNo
报警代码 AlarmCode
产品类型 ProductType
通信状态 StateCode

只要你面对的是这种:

同一个变量可能取多个值,而每个值对应不同处理,

那 CASE 往往比一长串 IF 更清楚。

十六、用步骤控制举例,你就知道 CASE 为什么很重要

假设一台设备的自动流程有这些步骤:

0 待机
10 夹紧
20 下压
30 保压
40 回原位
50 完成复位

如果你用 IF 写,可能会变成:

IF StepNo = 0 THEN
    ReadyLamp := TRUE;
END_IF;

IF StepNo = 10 THEN
    ClampCmd := TRUE;
END_IF;

IF StepNo = 20 THEN
    PressDownCmd := TRUE;
END_IF;

IF StepNo = 30 THEN
    HoldCmd := TRUE;
END_IF;

当然不是不能写,但整体感不够强。
因为这些分支明显都属于“同一个步骤变量的不同状态处理”。

如果改成 CASE:

CASE StepNo OF
    0:
        ReadyLamp := TRUE;

    10:
        ClampCmd := TRUE;

    20:
        PressDownCmd := TRUE;

    30:
        HoldCmd := TRUE;

    40:
        ReturnHomeCmd := TRUE;

    50:
        FinishFlag := TRUE;
END_CASE;

是不是一下就清楚很多。

这就是 CASE 的价值:
它把“围绕同一个状态变量的多个分支”组织得非常清晰。

所以以后你写顺控、状态机、模式切换时,CASE 会非常有用。

十七、CASE 适不适合写模式切换

非常适合。

例如一台设备有三种模式:

0 停止模式
1 手动模式
2 自动模式
3 调试模式

就可以写成:

CASE ModeNo OF
    0:
        AutoRun := FALSE;
        ManualEnable := FALSE;

    1:
        AutoRun := FALSE;
        ManualEnable := TRUE;

    2:
        AutoRun := TRUE;
        ManualEnable := FALSE;

    3:
        AutoRun := FALSE;
        ManualEnable := TRUE;
        DebugFlag := TRUE;
END_CASE;

这种写法比多个 IF 判断模式号更清楚。
因为模式本身就是一个“互斥状态集合”。

十八、CASE 能不能带默认处理

可以,很多平台里都支持用类似 ELSE 的方式表示没有匹配到任何分支时的处理。

例如思路上可以理解为:

当 StepNo 是 0、10、20 时按对应逻辑执行;
如果不是这些值,就走默认处理,比如回到安全状态、报警、复位等。

这在工程上很有价值。
因为程序运行时,不怕正常状态,就怕“落到不该有的状态”。

比如步骤号意外变成 999,或者模式号出现异常值,这时候默认分支就能起到保护作用。

一个思路示意如下:

CASE StepNo OF
    0:
        ReadyLamp := TRUE;

    10:
        ClampCmd := TRUE;

    20:
        FeedCmd := TRUE;

ELSE
    StepError := TRUE;
    StepNo := 0;
END_CASE;

这类写法在状态机里尤其值得重视。

十九、初学者用 CASE 时最容易犯的错误
第一种:把 CASE 用在本来更适合 IF 的场景

比如你只是想判断:

是否有故障
是否超过温度上限
是否满足启动许可

这些本质上是逻辑条件,而不是“一个变量多状态分支”。
这时候硬用 CASE 反而别扭。

第二种:把多个不同维度的逻辑塞进同一个 CASE

比如既处理步骤动作,又顺便处理报警,又顺便处理显示,又顺便处理统计。
结果 CASE 虽然围绕 StepNo 展开了,但内部内容过杂。

第三种:忘记 CASE 的核心是“围绕同一个变量”

CASE 最好服务于一个中心变量,比如:

StepNo
ModeNo
AlarmCode

如果你的判断本来涉及很多互不相关的条件,那还是 IF 更合适。

二十、工程上怎么判断 IF 写得清不清楚

这里给你一个很实用的标准。

你写完一段 IF 之后,问自己三个问题:

第一,这段逻辑能不能一句话读出来

例如:

“如果自动模式成立、没有故障且安全条件满足,就允许启动。”

如果能一句话清楚读出来,通常说明结构还不错。

第二,优先级是不是一眼能看出来

比如故障、急停、停止命令、启动命令的顺序,有没有体现出控制常识。

第三,别人接手时,能不能不用猜就知道你想干什么

程序不是写给当下这一秒的自己看的,而是写给未来调试、维护、修改的人看的。
这个人可能是同事,也可能是未来的你自己。

如果你写完一段 IF,自己一个月后都不愿意看,那多半就该改进了。

二十一、一个更接近工程的 IF 示例

下面给你一个更像现场程序的例子。
假设某段输送线启动前必须满足:

自动模式
没有急停
没有总故障
上游有放行
下游未满料
电机热继电器正常
启动按钮按下

程序可以这样写:

IF EStop THEN
    ConveyorRun := FALSE;

ELSIF GlobalFault THEN
    ConveyorRun := FALSE;

ELSIF NOT ThermalOK THEN
    ConveyorRun := FALSE;

ELSIF NOT AutoMode THEN
    ConveyorRun := FALSE;

ELSIF NOT UpstreamPermit THEN
    ConveyorRun := FALSE;

ELSIF DownstreamFull THEN
    ConveyorRun := FALSE;

ELSIF StartPB THEN
    ConveyorRun := TRUE;
END_IF;

这段程序的特点很典型:

第一,它是按优先级往下排的。
先停机保护类,再许可条件类,最后才是启动命令。

第二,它很适合调试。
因为你一眼就知道是在哪一层被拦下了。

第三,它是典型 PLC 思维。
不是炫技,也不是为了代码短,而是为了控制关系清楚。

当然,这段逻辑后期还可以优化,比如把运行许可单独整理成中间变量。
但作为判断思路,它已经非常实用了。

二十二、一个更接近工程的 CASE 示例

再看一个典型步骤控制示例。

CASE StepNo OF
    0:
        IF AutoStart THEN
            StepNo := 10;
        END_IF;

    10:
        ClampCmd := TRUE;
        IF ClampFB THEN
            StepNo := 20;
        END_IF;

    20:
        PressDownCmd := TRUE;
        IF DownPosFB THEN
            StepNo := 30;
        END_IF;

    30:
        HoldCmd := TRUE;
        IF HoldTimeDone THEN
            StepNo := 40;
        END_IF;

    40:
        ReturnCmd := TRUE;
        IF HomeFB THEN
            StepNo := 50;
        END_IF;

    50:
        FinishFlag := TRUE;
        StepNo := 0;

ELSE
    StepError := TRUE;
    StepNo := 0;
END_CASE;

这段程序很能体现 CASE 的价值。

因为整个流程就是围绕 StepNo 这个核心变量展开的。
每个步骤有自己的动作,也有跳转到下一步的条件。

如果用一长串 IF 来写,不是不能写,但结构感会差很多。
而 CASE 一眼就把整个流程分区展示出来了。

二十三、IF 和 CASE 在实际项目里往往不是二选一,而是配合使用

这一点很重要。

很多初学者会问:

“到底用 IF 还是 CASE?”

真实工程里,往往不是只能选一个,而是配合使用。

例如在步骤控制里:

大框架用 CASE,按步骤分区
每个步骤内部,再用 IF 判断动作完成条件

就像刚才那个例子一样:

CASE 决定“当前在哪一步”
IF 决定“这一步什么时候跳到下一步”

这就是很典型、也很成熟的 SCL 写法。

所以你要建立一个观念:

IF 负责条件判断,CASE 负责状态分支,它们经常是搭配出现的。

二十四、条件判断写得好的一个秘诀:先用人话说清楚,再翻成 SCL

这是我非常建议你养成的习惯。

比如某段逻辑,你先不要着急敲代码。
先在纸上或脑子里说清楚:

如果急停按下,就停机。
否则如果有故障,也停机。
否则如果停止按钮按下,就停机。
否则如果自动模式且启动按钮按下,就运行。

等这句话顺了,再写成:

IF EStop THEN
    MotorRun := FALSE;
ELSIF Fault THEN
    MotorRun := FALSE;
ELSIF StopPB THEN
    MotorRun := FALSE;
ELSIF AutoMode AND StartPB THEN
    MotorRun := TRUE;
END_IF;

你会发现,这样写程序比一边想一边乱堆条件顺很多。

SCL 最怕的不是语法多,而是思路没整理就直接开写。
一旦思路先清楚,IF 和 CASE 都会自然很多。

二十五、这一篇最后,给你几个非常实用的工程建议
第一,先排高优先级条件,再排普通条件

尤其是安全、急停、故障、停止类逻辑,一般都应该放前面。

第二,复杂条件尽量提炼成中间变量

不要什么都硬塞进一行 IF 里。
程序不是越紧凑越高级,而是越清楚越值钱。

第三,嵌套可以用,但尽量别太深

超过三层以后,就要开始考虑是否能优化结构。

第四,一个变量多状态分支,优先考虑 CASE

特别是步骤号、模式号、状态码这类变量。

第五,写完判断后,用中文顺读一遍

能顺着读出来,通常结构就比较合理。
读着磕巴,程序多半也不够清楚。

小结

这一篇你最应该记住这些核心点:

IF 适合做条件判断,CASE 适合做多状态分支。
ELSIF 的本质是按优先级一层一层筛选。
ELSE 用来处理条件不成立时的另一种明确结果。
PLC 程序里,判断顺序非常重要,尤其是故障和安全条件的优先级必须清楚。
复杂条件不要一味堆在一行里,必要时要拆成中间变量。
步骤控制、状态机、模式切换这类逻辑,CASE 往往比多重 IF 更清楚。
在实际项目里,CASE 和 IF 经常配合使用,而不是互相替代。
下载资料前请先绑定手机号码