4、ST结构化文本基础:变量声明、数据类型、运算符、表达式与赋值语句的编写

ST(Structured Text,结构化文本)是IEC 61131-3标准中语法最接近高级编程语言(如Pascal、C)的PLC编程语言。它不像梯形图那样强调电气回路的视觉逻辑,而是通过清晰的语句结构、严格的数据类型和灵活的表达式来构建控制算法。对于从事工业自动化开发的工程师而言,ST语言在数据处理、数学运算、复杂流程控制以及算法实现方面具有无可替代的优势。本章将围绕ST语言的四大核心基础——变量声明、数据类型、运算符与表达式、赋值语句——展开系统讲解,帮助你在Codesys环境中快速建立扎实的ST编程功底。

ST结构化文本核心知识框架 ST语言基础 变量声明 VAR / VAR_INPUT / VAR_OUTPUT 数据类型 BOOL / INT / REAL / STRING / TIME 运算符与表达式 算术 / 比较 / 逻辑 / 位运算 赋值语句 := 与表达式组合应用 工程应用:PID运算、逻辑联锁、数据处理、运动控制 类型安全 → 代码健壮性 | 表达式优化 → 执行效率

上图展示了ST语言基础知识的整体架构。变量声明是数据的容器定义,数据类型决定了数据的存储方式与取值范围,运算符与表达式构成了数据处理的核心逻辑,而赋值语句则是将计算结果写入变量的桥梁。这四者环环相扣,共同构成了ST编程的最小闭环。下面我们将逐一深入剖析。

4.1 变量声明:从内存分配到作用域控制

核心原理:在ST语言中,变量声明不仅是为数据分配内存空间,更重要的是通过关键字定义变量的作用域(局部/全局)、存储属性(保持/非保持)以及访问权限(输入/输出/内部)。Codesys遵循IEC 61131-3标准,提供了丰富的声明区关键字。

声明关键字作用域典型用途示例
VARPOU内部局部变量临时计算、中间结果VAR temp : INT; END_VAR
VAR_INPUT函数/功能块输入外部传入参数VAR_INPUT setpoint : REAL; END_VAR
VAR_OUTPUT函数/功能块输出返回计算结果VAR_OUTPUT actual : REAL; END_VAR
VAR_IN_OUT输入输出双向需要修改的外部变量VAR_IN_OUT counter : INT; END_VAR
VAR_GLOBAL全局变量跨POU共享数据VAR_GLOBAL g_mode : INT; END_VAR
VAR RETAIN保持变量断电保持数据VAR RETAIN recipe_no : INT; END_VAR

操作流程:在Codesys中声明变量时,应遵循以下步骤:

  1. 在POU(程序组织单元)编辑区顶部,根据变量用途选择正确的声明区关键字。
  2. 为变量指定合法的标识符(以字母或下划线开头,不能包含空格和特殊字符)。
  3. 明确数据类型,必要时添加初始值(如 VAR speed : REAL := 100.0; END_VAR)。
  4. 对于需要掉电保持的数据,使用 RETAIN 修饰;对于需要网络可视化的变量,可添加属性注释。

实战场景:假设我们需要编写一个电机速度控制功能块,输入为目标速度,输出为实际速度,内部需要累计误差。声明如下:

FUNCTION_BLOCK FB_MotorCtrl
VAR_INPUT
    bEnable   : BOOL;      // 使能信号
    rSetSpeed : REAL;      // 目标速度 (rpm)
END_VAR
VAR_OUTPUT
    rActSpeed : REAL;      // 实际速度反馈
    bRunning  : BOOL;      // 运行状态
END_VAR
VAR
    rErrorAcc : REAL := 0.0;  // 误差累计值
    rLastSpeed : REAL;        // 上次速度
END_VAR

常见误区:初学者容易混淆 VAR_IN_OUT 与 VAR_OUTPUT。前者传递的是引用(指针),修改会直接影响外部实参;后者是值拷贝,仅在功能块内部修改后输出。错误使用 VAR_IN_OUT 可能导致外部变量被意外修改,引发逻辑混乱。

4.2 数据类型:选择正确的数据容器

核心原理:ST语言是强类型语言,所有变量必须明确数据类型。数据类型决定了变量的存储大小、取值范围以及可参与的运算。Codesys支持标准IEC数据类型,并扩展了部分自定义类型。

类别类型位宽取值范围典型应用
布尔BOOL1位TRUE / FALSE状态标志、联锁条件
整数INT16位-32768 ~ 32767计数器、索引
整数DINT32位-2^31 ~ 2^31-1大范围计数
浮点REAL32位±3.4E38模拟量、PID计算
浮点LREAL64位±1.7E308高精度计算
时间TIME32位0 ~ 49天定时器、延时
字符串STRING可变字符序列报警信息、配方名

判断方法:选择数据类型时,应遵循“够用、留余量、防溢出”的原则。例如,计数范围不超过1000时选INT即可;涉及温度、压力等模拟量时,必须使用REAL;需要精确到小数点后6位以上时,考虑LREAL。同时要注意,不同整数类型之间运算时,Codesys会自动进行隐式转换,但可能产生精度损失或溢出,建议使用类型转换函数(如 INT_TO_REAL)显式转换。

经验提醒:在PLC编程中,尽量避免使用LREAL,因为大多数PLC的浮点运算单元(FPU)对REAL(32位)的优化更好,运算速度更快。LREAL在Codesys软PLC中支持较好,但在硬PLC中可能性能下降。

4.3 运算符与表达式:构建控制逻辑的基石

核心原理:ST语言提供了丰富的运算符,包括算术运算符、比较运算符、逻辑运算符和位运算符。表达式是由变量、常量、运算符和函数调用组成的合法序列,其求值遵循优先级规则。

类别运算符说明优先级
括号( )改变优先级最高
函数调用FUNC()如 ABS(), SQRT()高
算术* / MOD乘、除、取余中高
算术+ -加、减中
比较< > <= >=大小比较中低
比较= <>等于、不等于低
逻辑AND OR XOR与、或、异或更低
逻辑NOT非最低

操作流程:编写表达式时,建议遵循以下步骤:

  1. 明确表达式的目标输出类型(BOOL、数值等)。
  2. 将复杂表达式拆分为多个中间变量,提高可读性。
  3. 使用括号明确运算顺序,避免依赖默认优先级。
  4. 注意短路求值:AND 和 OR 在左侧结果已确定时,右侧不再求值。

案例拆解:某设备需要实现以下联锁逻辑:当温度超过80℃且(压力超过1.5MPa或运行时间超过2小时)时,触发报警并停止电机。ST表达式如下:

// 变量声明
VAR
    rTemp   : REAL := 85.0;   // 当前温度
    rPress  : REAL := 1.6;    // 当前压力
    tRun    : TIME := T#2H30M; // 运行时间
    bAlarm  : BOOL;
    bStop   : BOOL;
END_VAR

// 联锁逻辑
bAlarm := (rTemp > 80.0) AND ((rPress > 1.5) OR (tRun > T#2H));
bStop  := bAlarm;  // 触发停止

该表达式清晰表达了三个条件的组合关系。注意 TIME 类型使用 T# 前缀表示时间常量。

常见误区:在ST中,赋值运算符是 :=,而比较相等是 =。初学者常将C语言习惯带入,使用 = 进行赋值,导致编译错误。另外,逻辑运算符 AND、OR 不能写成 && 或 ||。

4.4 赋值语句与表达式综合应用

核心原理:赋值语句是ST程序中最基本的执行单元,格式为 变量 := 表达式;。赋值语句的执行过程是:先计算右侧表达式的值,再将其转换为左侧变量的数据类型,最后写入变量。赋值语句可以连续使用,也可以与条件语句结合实现复杂控制。

操作流程:编写赋值语句时,需注意以下几点:

  • 左侧必须是可写变量(不能是常量或输入变量)。
  • 右侧表达式的结果类型应与左侧变量类型兼容,否则需要显式转换。
  • 赋值语句以分号 ; 结尾,一行可写多条语句。
  • 可以使用 := 进行链式赋值,如 a := b := c := 0;,但可读性较差,不推荐。

实战场景:以一个简单的PID控制器核心计算为例,展示赋值语句与表达式的综合运用:

// PID计算(位置式)
VAR
    rKp, rKi, rKd : REAL;      // PID参数
    rSet, rFb     : REAL;      // 设定值与反馈值
    rErr, rErrSum : REAL;      // 误差与误差累计
    rLastErr      : REAL;      // 上次误差
    rOut          : REAL;      // 输出值
    rDeltaT       : TIME;      // 采样周期
END_VAR

// 计算误差
rErr := rSet - rFb;
// 累计误差(带限幅)
rErrSum := rErrSum + rErr;
IF rErrSum > 100.0 THEN
    rErrSum := 100.0;
ELSIF rErrSum < -100.0 THEN
    rErrSum := -100.0;
END_IF
// PID输出
rOut := rKp * rErr + rKi * rErrSum + rKd * (rErr - rLastErr) / TIME_TO_REAL(rDeltaT);
// 更新上次误差
rLastErr := rErr;

总结复盘:本章围绕ST语言的四大基础模块展开。变量声明是数据管理的基础,数据类型是安全编程的保障,运算符与表达式是逻辑构建的工具,赋值语句是数据流动的通道。在实际工程中,建议遵循以下原则:

  • 类型安全优先:所有变量显式声明类型,避免隐式转换。
  • 可读性优先:复杂表达式拆分为多个简单语句,添加必要注释。
  • 边界防护:对累计值、计算输出进行限幅,防止溢出。
  • 命名规范:使用匈牙利命名法(如 rSpeed 表示REAL类型速度,bEnable 表示BOOL使能)。

经验提醒:在Codesys中,可以使用 变量监视 窗口实时查看变量值变化,调试赋值语句时,建议设置断点并单步执行,观察表达式求值过程,这比直接运行后看结果更高效。

掌握这些基础后,你将能够编写出结构清晰、逻辑严谨的ST程序。下一阶段的学习中,我们将在此基础上引入条件语句(IF/CASE)和循环语句(FOR/WHILE),构建更复杂的控制流程。