文章目录

ST状态机编程模板:用 CASE 语句实现标准的顺序控制流程

发布于 2026-03-19 15:24:52 · 浏览 7 次 · 评论 0 条

ST状态机编程模板:用 CASE 语句实现标准的顺序控制流程

在电气自动化系统中,顺序控制是最常见、最核心的控制类型之一。它广泛应用于包装机械、装配线、灌装设备、电梯逻辑、锅炉启停等场景。这类任务的共性是:动作严格按阶段推进,每个阶段有明确的启动条件、执行动作、完成判据和转移路径。若用传统梯形图(LAD)实现复杂顺序,容易陷入“线网缠绕、跳转难查、调试费时”的困境;而结构化文本(ST)语言凭借其接近自然语言的逻辑表达能力、清晰的分支结构与变量管理机制,成为构建高可靠性顺序控制的理想载体。

本文提供一套经工业现场验证的 ST 状态机编程模板,完全基于 IEC 61131-3 标准的 CASE 语句实现,不依赖厂商扩展指令,可直接用于 Codesys、TIA Portal(SCL 模式)、Unity Pro、GX Works3(ST 编辑器)等主流 PLC 平台。全文聚焦“可读性、可维护性、抗干扰性”三大工程刚需,所有代码片段均可复制粘贴后编译运行。


一、为什么必须用状态机?——顺序控制的本质矛盾

顺序控制不是“一步到位”,而是“分步裁决”。典型问题包括:

  • 同一物理输出(如电机启停)在不同阶段含义不同(阶段1启动→阶段2保持→阶段3停止);
  • 某一条件(如“门已关”)在阶段A是启动前提,在阶段B却是故障禁止条件;
  • 手动干预(如急停、暂停)需中断当前流程,但不能丢失上下文。

若用 IF-ELSE 嵌套实现,代码将迅速退化为“意大利面条式逻辑”:

IF (Step1_Start AND NOT Step1_Done) THEN
  Motor := TRUE;
  IF Sensor_A THEN Step1_Done := TRUE; END_IF;
ELSIF (Step1_Done AND Step2_Start AND NOT Step2_Done) THEN
  Valve := TRUE;
  IF Timer2.Q THEN Step2_Done := TRUE; END_IF;
  // …… 几十层嵌套后,谁还记得 Step17 的退出条件?
END_IF;

而状态机将控制逻辑与状态数据分离

  • State 变量唯一标识当前所处阶段(如 STATE_IDLE, STATE_FILL, STATE_SEAL);
  • 每个 CASE 分支只专注本阶段的三件事:执行动作、判断转移条件、设置下一状态;
  • 所有状态转移由显式 State := NEXT_STATE 控制,无隐式跳转,逻辑流向一目了然。

二、标准状态机四要素(缺一不可)

一个工业级状态机必须包含以下四个组成部分,否则无法应对真实产线需求:

  1. 状态枚举定义(Type Declaration)
    使用 TYPE ... END_TYPE 明确定义所有合法状态,禁止用整数或字符串硬编码。

    TYPE T_State :
    (
        STATE_IDLE,        // 待机:等待启动命令
        STATE_STARTUP,     // 启动:上电自检、安全复位
        STATE_FILL,        // 填充:打开进料阀,启动输送带
        STATE_SEAL,        // 封口:下降压头,加热定时
        STATE_EJECT,       // 推出:打开出料气缸,延时返回
        STATE_ERROR        // 故障:所有输出置0,等待人工确认
    );
    END_TYPE
  2. 状态变量与持久化存储
    State 必须声明为 RETAIN(保持型),确保 PLC 断电重启后不丢失当前阶段:

    VAR
        State : T_State := STATE_IDLE;  // 初始值设为待机
        State_Prev : T_State;            // 记录上一状态(用于边缘触发)
    END_VAR
  3. 主状态机循环(Main CASE Block)
    在主程序组织块(POU)中,用 CASE State OF 包裹全部逻辑:

    CASE State OF
        STATE_IDLE:
            // 待机阶段动作
            Motor := FALSE;
            Valve := FALSE;
            Heater := FALSE;
            // 转移条件:收到启动信号且无故障
            IF Start_Button AND NOT Fault_Flag THEN
                State := STATE_STARTUP;
            END_IF;
    
        STATE_STARTUP:
            // 启动阶段动作:执行自检序列
            SelfTest_InProgress := TRUE;
            // 完成判据:所有传感器反馈正常 + 安全门关闭
            IF SelfTest_Done AND Safety_Door_Closed THEN
                State := STATE_FILL;
            ELSIF SelfTest_Failed THEN
                State := STATE_ERROR;
            END_IF;
    
        STATE_FILL:
            // 填充阶段动作
            Valve := TRUE;                // 打开进料阀
            Conveyor_Belt := TRUE;        // 启动输送带
            // 完成判据:料位传感器检测满料 OR 时间超限(防堵料)
            IF Level_Sensor_High OR Fill_Timer.Q THEN
                Valve := FALSE;           // 关阀
                Conveyor_Belt := FALSE;   // 停带
                State := STATE_SEAL;
            END_IF;
    
        STATE_SEAL:
            // 封口阶段动作
            Press_Down := TRUE;           // 下降压头
            Heater := TRUE;               // 启动加热
            // 完成判据:压头到位 + 加热时间到
            IF Press_Down_OK AND Heater_Timer.Q THEN
                Press_Up := TRUE;         // 抬起压头
                Heater := FALSE;
                State := STATE_EJECT;
            END_IF;
    
        STATE_EJECT:
            // 推出阶段动作
            Eject_Cylinder := TRUE;       // 推出气缸伸出
            // 完成判据:推出到位 + 延时确保工件落槽
            IF Eject_Ext_OK AND Eject_Delay.Q THEN
                Eject_Cylinder := FALSE;  // 气缸缩回
                State := STATE_IDLE;
            END_IF;
    
        STATE_ERROR:
            // 故障阶段动作:强制安全停机
            Motor := FALSE;
            Valve := FALSE;
            Heater := FALSE;
            Press_Down := FALSE;
            Press_Up := FALSE;
            Eject_Cylinder := FALSE;
            // 转移条件:故障复位按钮按下 + 故障已清除
            IF Reset_Button AND NOT Fault_Flag THEN
                State := STATE_IDLE;
            END_IF;
    END_CASE;
  4. 状态变迁记录(可选但强烈推荐)
    为调试与追溯增加状态切换日志:

    // 在主 CASE 块外添加
    IF State <> State_Prev THEN
        State_Change_Time := T#NOW;  // 记录切换时刻
        State_Change_Count := State_Change_Count + 1;
    END_IF;
    State_Prev := State;

三、关键工程实践(避坑指南)

▶ 条件判断必须“去抖+闭锁”,严禁裸信号

传感器信号存在机械抖动、电磁干扰,直接使用 IF Sensor THEN 会导致状态反复跳变。正确做法:

  • 对所有输入信号(尤其是按钮、限位开关)加 TP(脉冲定时器)或 R_TRIG(上升沿触发器)滤波;

  • 对关键完成条件(如 Fill_Timer.Q)增加“确认延迟”:

    // 错误示例:Timer.Q 一变TRUE立即转移
    IF Fill_Timer.Q THEN State := STATE_SEAL; END_IF;
    
    // 正确示例:需连续200ms为TRUE才认可
    FILL_CONFIRM: TP(T#200MS);
    FILL_CONFIRM(IN := Fill_Timer.Q);
    IF FILL_CONFIRM.Q THEN State := STATE_SEAL; END_IF;

▶ 输出必须“双重约束”:状态驱动 + 安全使能

即使处于 STATE_FILL,若安全门意外打开,进料阀也必须立即关闭。因此所有输出需满足:

Valve := (State = STATE_FILL) AND Safety_Enable;
Conveyor_Belt := (State = STATE_FILL) AND Safety_Enable AND No_Jam;

其中 Safety_Enable 是全局安全使能信号(由急停、门锁、光幕等串联生成)。

▶ 支持暂停/恢复的增强设计

STATE_FILLSTATE_SEAL 等长周期阶段,增加暂停功能:

// 在 STATE_FILL 分支内插入
IF Pause_Button THEN
    Conveyor_Belt := FALSE;
    Valve := FALSE;
    Fill_Pause_Timer(IN := TRUE, PT := T#5S); // 暂停超时自动转入ERROR
    IF Fill_Pause_Timer.Q THEN State := STATE_ERROR; END_IF;
ELSIF Resume_Button THEN
    Conveyor_Belt := TRUE;
    Valve := TRUE;
END_IF;

▶ 故障处理必须分级响应

  • 一级故障(如温度超限):暂停当前阶段,尝试自动恢复;
  • 二级故障(如安全门开):立即转入 STATE_ERROR,切断所有输出;
  • 故障代码必须写入 Fault_Code 全局变量,并通过 HMI 显示具体原因(如 Fault_Code := 102; // "Sealing temp too high")。

四、完整可运行模板(含初始化与安全兜底)

以下为可直接部署的最小可行模板(适用于任何支持 ST 的 PLC):

// ====== 声明区 ======
TYPE T_State : (STATE_IDLE, STATE_STARTUP, STATE_RUN, STATE_STOP, STATE_ERROR);
END_TYPE

VAR
    State : T_State := STATE_IDLE;
    State_Prev : T_State;

    // 输入信号(根据实际IO映射)
    Start_Button : BOOL;
    Stop_Button : BOOL;
    Safety_Enable : BOOL;  // 急停、门锁、光幕串联
    Sensor_Full : BOOL;

    // 输出信号
    Motor : BOOL;
    Valve : BOOL;

    // 内部定时器(需在PLC资源中配置)
    Startup_Timer : TON;
    Run_Timer : TON;
    Stop_Timer : TON;

    // 故障管理
    Fault_Flag : BOOL;
    Fault_Code : INT := 0;
END_VAR

// ====== 主逻辑区 ======
// 安全兜底:任何时刻 Safety_Enable 失效,强制进入 ERROR
IF NOT Safety_Enable THEN
    State := STATE_ERROR;
    Fault_Code := 1;
END_IF;

// 主状态机
CASE State OF
    STATE_IDLE:
        Motor := FALSE;
        Valve := FALSE;
        IF Start_Button AND NOT Fault_Flag THEN
            State := STATE_STARTUP;
        END_IF;

    STATE_STARTUP:
        Startup_Timer(IN := TRUE, PT := T#3S);
        IF Startup_Timer.Q THEN
            State := STATE_RUN;
        END_IF;

    STATE_RUN:
        Motor := TRUE;
        Valve := TRUE;
        Run_Timer(IN := TRUE, PT := T#10S);
        IF Sensor_Full OR Run_Timer.Q THEN
            State := STATE_STOP;
        END_IF;

    STATE_STOP:
        Motor := FALSE;
        Valve := FALSE;
        Stop_Timer(IN := TRUE, PT := T#2S);
        IF Stop_Timer.Q THEN
            State := STATE_IDLE;
        END_IF;

    STATE_ERROR:
        Motor := FALSE;
        Valve := FALSE;
        IF Stop_Button THEN  // 仅允许通过停止按钮复位
            Fault_Flag := FALSE;
            Fault_Code := 0;
            State := STATE_IDLE;
        END_IF;
END_CASE;

// 状态变迁记录(用于HMI诊断)
IF State <> State_Prev THEN
    State_Prev := State;
END_IF;

五、调试与验证清单

验证项 操作方法 预期结果
单步模拟 在仿真环境手动置位 Start_Button,观察 State 变量变化 STATE_IDLE → STATE_STARTUP → STATE_RUN → STATE_STOP → STATE_IDLE 循环准确
急停测试 STATE_RUN 时断开 Safety_Enable State 立即变为 STATE_ERRORMotorValve 瞬间为 FALSE
故障注入 强制 Fault_Flag := TRUE 当前阶段立即终止,转入 STATE_ERRORStop_Button 后清除故障并返回 STATE_IDLE
边界压力 连续快速点按 Start_Button(<100ms间隔) State 不发生重复跳变,仅响应首个有效边沿

六、进阶提示:从 CASE 到模块化

当设备包含多个独立工序(如“主输送线+分拣臂+打标机”),应将每个工序封装为独立的 FB(功能块):

FUNCTION_BLOCK FB_Filling_Station
VAR_INPUT
    Start_Cmd : BOOL;
    Safety_OK : BOOL;
    Full_Sensor : BOOL;
END_VAR
VAR_OUTPUT
    Is_Running : BOOL;
    Error_Code : INT;
END_VAR
VAR
    State : T_State := STATE_IDLE;
    Timer : TON;
END_VAR
// 内部使用完全相同的 CASE 结构

主程序调用:

Filling_Station(Start_Cmd := Main_Start, Safety_OK := Safety_Main, Full_Sensor := Level_High);
Packing_Arm(Start_Cmd := Filling_Station.Is_Running, ...);

此设计实现高内聚、低耦合,任一单元故障不影响其他单元,且支持热插拔替换。


状态机不是编程技巧,而是对控制本质的敬畏。每一个 CASE 分支都是对物理世界一个确定阶段的忠实建模,每一次 State := ... 都是对系统演进路径的主动掌控。坚持使用本模板,你交付的将不再是“能跑的程序”,而是“可读、可测、可扩展、可传承”的自动化资产。

评论 (0)

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

扫一扫,手机查看

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