博文

IEC61131-3 ST语言进阶 - 最佳实践与工业实战案例库

ST/PLC

IEC61131-3 ST 语言进阶 - 最佳实践与工业实战案例库

1. 编程最佳实践

1.1 命名规范

类型规范示例
变量驼峰式或下划线MotorSpeed, motor_speed
常量全大写MAX_SPEED, PI_VALUE
功能块FB_ 前缀FB_MotorControl
函数FC_ 前缀FC_Calculate
全局变量g_ 前缀g_SystemMode
类型TYPE_ 前缀TYPE_MotorParams

1.2 性能优化

// ❌ 不好:循环中重复计算
FOR i := 0 TO 99 DO
    Sum := Sum + Data[i];
    Size := UPPER_BOUND(Data, 1);  // 每次都调用
END_FOR;

// ✅ 好:循环外计算
ArraySize := UPPER_BOUND(Data, 1);  // 循环外
FOR i := 0 TO ArraySize - 1 DO
    Sum := Sum + Data[i];
END_FOR;

// ❌ 不好:不必要的类型转换
FOR i := 0 TO 99 DO
    Result := Result + REAL(INT_TO_REAL(i) * 0.1);
END_FOR;

// ✅ 好:缓存转换结果
RealIncrement := 0.1;
FOR i := 0 TO 99 DO
    Result := Result + INT_TO_REAL(i) * RealIncrement;
END_FOR;

1.3 代码结构建议

// 推荐的结构
FUNCTION_BLOCK FB_Example
// 1. 输入输出声明
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR

// 2. 内部变量声明
VAR
END_VAR

// 3. 常量声明
VAR CONSTANT
END_VAR

// 4. 逻辑实现
// 输入验证
// 状态机/主要逻辑
// 输出处理

END_FUNCTION_BLOCK

2. 实战案例:温度控制

2.1 PID 温控功能块

FUNCTION_BLOCK FB_TemperatureControl
VAR_INPUT
    SetPoint : REAL;          // 目标温度
    ActualTemp : REAL;        // 实际温度
    AutoMode : BOOL;          // 自动模式
    Reset : BOOL;             // 复位
    Enable : BOOL;            // 使能
END_VAR
VAR_OUTPUT
    HeaterOutput : REAL;      // 加热器输出 0-100%
    AlarmHigh : BOOL;         // 高温报警
    AlarmLow : BOOL;          // 低温报警
    InRange : BOOL;           // 温度在范围内
END_VAR
VAR
    // PID 参数
    Kp : REAL := 2.0;
    Ti : REAL := 30.0;        // 积分时间
    Td : REAL := 5.0;         // 微分时间
    
    // 内部变量
    Error : REAL;
    Integral : REAL;
    PrevError : REAL;
    Output : REAL;
    Tolerance : REAL := 2.0;  // 容差 ±2°C
END_VAR

// 使能检查
IF NOT Enable THEN
    HeaterOutput := 0.0;
    RETURN;
END_IF;

// 误差计算
Error := SetPoint - ActualTemp;

// 报警检查
AlarmHigh := ActualTemp > (SetPoint + 10.0);
AlarmLow := ActualTemp < (SetPoint - 10.0);
InRange := ABS(Error) <= Tolerance;

// 手动模式
IF NOT AutoMode THEN
    HeaterOutput := 0.0;
    RETURN;
END_IF;

// 复位
IF Reset THEN
    Integral := 0.0;
    PrevError := 0.0;
    HeaterOutput := 0.0;
    RETURN;
END_IF;

// PID 计算
// 比例
Output := Kp * Error;

// 积分(带抗积分饱和)
IF NOT ((Output > 90.0 AND Error > 0.0) OR 
        (Output < 10.0 AND Error < 0.0)) THEN
    Integral := Integral + (Error / Ti);
END_IF;
Output := Output + Integral;

// 微分
Output := Output + Td * (Error - PrevError);
PrevError := Error;

// 限幅 0-100%
IF Output > 100.0 THEN
    Output := 100.0;
ELSIF Output < 0.0 THEN
    Output := 0.0;
END_IF;

HeaterOutput := Output;

END_FUNCTION_BLOCK

3. 实战案例:简易运动控制

3.1 位置控制功能块

FUNCTION_BLOCK FB_SimpleMotion
VAR_INPUT
    TargetPosition : DINT;    // 目标位置
    Velocity : REAL;          // 运行速度
    Acceleration : REAL;      // 加速度
    Start : BOOL;             // 启动
    Stop : BOOL;              // 停止
    Home : BOOL;              // 回零
    Enable : BOOL;            // 使能
END_VAR
VAR_OUTPUT
    CurrentPosition : DINT;   // 当前位置
    CurrentVelocity : REAL;   // 当前速度
    Busy : BOOL;              // 运动中
    Done : BOOL;              // 到位
    Error : BOOL;             // 错误
    ErrorID : INT;            // 错误码
    InPosition : BOOL;        // 到位
    PosTolerance : DINT := 10;// 到位容差
END_VAR
VAR
    MoveState : INT := 0;     // 0:空闲 1:加速 2:匀速 3:减速 4:到位
    RampVel : REAL;
END_VAR

IF NOT Enable THEN
    CurrentVelocity := 0.0;
    Busy := FALSE;
    RETURN;
END_IF;

// 错误检查
IF TargetPosition < 0 OR TargetPosition > 1000000 THEN
    Error := TRUE;
    ErrorID := 1;  // 超限位
    RETURN;
END_IF;

CASE MoveState OF
    0:  // 空闲
        Done := ABS(CurrentPosition - TargetPosition) <= PosTolerance;
        IF Start AND NOT Done AND NOT Error THEN
            MoveState := 1;
            Busy := TRUE;
            Done := FALSE;
            RampVel := 0.0;
        END_IF;
        IF Home THEN
            CurrentPosition := 0;
        END_IF;
    
    1:  // 加速阶段
        RampVel := RampVel + Acceleration;
        IF RampVel >= Velocity THEN
            RampVel := Velocity;
            MoveState := 2;
        END_IF;
        Move_State_Run();
    
    2:  // 匀速阶段
        Move_State_Run();
        // 检查是否需要减速
        IF ABS(TargetPosition - CurrentPosition) <= Decel_Distance() THEN
            MoveState := 3;
        END_IF;
        IF Stop THEN
            MoveState := 3;
        END_IF;
    
    3:  // 减速阶段
        RampVel := RampVel - Acceleration;
        IF RampVel <= 0.0 THEN
            RampVel := 0.0;
            MoveState := 4;
        END_IF;
        Move_State_Run();
    
    4:  // 到位
        CurrentPosition := TargetPosition;
        CurrentVelocity := 0.0;
        Busy := FALSE;
        Done := TRUE;
        IF Start AND ABS(TargetPosition - CurrentPosition) > PosTolerance THEN
            MoveState := 0;
        END_IF;
END_CASE;

InPosition := Done;

// 内部运动计算过程
END_FUNCTION_BLOCK

// 辅助函数
FUNCTION Decel_Distance : REAL
VAR_INPUT
    Velocity : REAL;
    Acceleration : REAL;
END_VAR
    Decel_Distance := (Velocity * Velocity) / (2.0 * Acceleration);
END_FUNCTION

4. 实战案例:数据记录器

4.1 循环缓冲区数据记录

FUNCTION_BLOCK FB_DataLogger
VAR_INPUT
    Enable : BOOL;
    SampleTime : TIME := T#1s;
    Channel1 : REAL;
    Channel2 : REAL;
    Channel3 : REAL;
    ClearHistory : BOOL;
END_VAR
VAR_OUTPUT
    RecordCount : INT;
    BufferFull : BOOL;
    WriteIndex : INT;
END_VAR
VAR
    // 循环缓冲区
    Buffer : ARRAY[0..999] OF STRUCT
        Timestamp : TIME;
        CH1 : REAL;
        CH2 : REAL;
        CH3 : REAL;
    END_STRUCT;
    
    SampleTimer : TON;
    MaxRecords : CONSTANT INT := 1000;
END_VAR

// 采样定时器
SampleTimer(IN := Enable, PT := SampleTime);

IF SampleTimer.Q THEN
    SampleTimer(IN := FALSE);
    SampleTimer(IN := Enable);
    
    // 记录数据
    Buffer[WriteIndex].Timestamp := SampleTimer.ET;
    Buffer[WriteIndex].CH1 := Channel1;
    Buffer[WriteIndex].CH2 := Channel2;
    Buffer[WriteIndex].CH3 := Channel3;
    
    WriteIndex := WriteIndex + 1;
    IF WriteIndex >= MaxRecords THEN
        WriteIndex := 0;
        BufferFull := TRUE;
    END_IF;
    
    RecordCount := RecordCount + 1;
END_IF;

// 清除历史
IF ClearHistory THEN
    WriteIndex := 0;
    RecordCount := 0;
    BufferFull := FALSE;
END_IF;

END_FUNCTION_BLOCK

5. 常用设计模式

5.1 上升沿/下降沿检测

// 功能块实现
FUNCTION_BLOCK FB_EdgeDetect
VAR_INPUT
    Signal : BOOL;
END_VAR
VAR_OUTPUT
    RisingEdge : BOOL;
    FallingEdge : BOOL;
END_VAR
VAR
    PrevSignal : BOOL;
END_VAR

RisingEdge := Signal AND NOT PrevSignal;
FallingEdge := NOT Signal AND PrevSignal;
PrevSignal := Signal;

END_FUNCTION_BLOCK

// 使用
VAR
    EdgeDetector : FB_EdgeDetect;
END_VAR

EdgeDetector(Signal := InputSignal);

IF EdgeDetector.RisingEdge THEN
    // 上升沿触发
    Count := Count + 1;
END_IF;

5.2 限幅函数

FUNCTION FC_Limit : REAL
VAR_INPUT
    Value : REAL;
    MinVal : REAL;
    MaxVal : REAL;
END_VAR

IF Value > MaxVal THEN
    FC_Limit := MaxVal;
ELSIF Value < MinVal THEN
    FC_Limit := MinVal;
ELSE
    FC_Limit := Value;
END_IF;

END_FUNCTION

// 使用
Output := FC_Limit(Input, 0.0, 100.0);

5.3 死区函数

FUNCTION FC_DeadBand : REAL
VAR_INPUT
    Value : REAL;
    DeadBand : REAL;
END_VAR

IF ABS(Value) <= DeadBand THEN
    FC_DeadBand := 0.0;
ELSIF Value > 0.0 THEN
    FC_DeadBand := Value - DeadBand;
ELSE
    FC_DeadBand := Value + DeadBand;
END_IF;

END_FUNCTION

6. 附录:ST 常用标准库函数

数学函数

函数说明
ABS(x)绝对值
SQRT(x)平方根
LN(x)自然对数
LOG(x)常用对数
EXP(x)指数
SIN/COS/TAN(x)三角函数
ASIN/ACOS/ATAN(x)反三角函数

数值处理

函数说明
TRUNC(x)截断取整
ROUND(x)四舍五入
FLOOR(x)向下取整
CEIL(x)向上取整
MAX(a, b)最大值
MIN(a, b)最小值
LIMIT(Min, Value, Max)限幅

字符串函数

函数说明
LEN(s)字符串长度
CONCAT(s1, s2)连接
LEFT(s, n)左截取 n 个字符
RIGHT(s, n)右截取 n 个字符
MID(s, start, len)截取子串
FIND(s1, s2)查找位置
INSERT(s1, s2, pos)插入
DELETE(s, pos, len)删除
REPLACE(s1, s2, s3)替换
UPPER(s) / LOWER(s)大小写转换

文档版本:1.0 | 更新日期:2026-04-28 | 作者:JianLin Studio

← 返回博文列表