4、ST结构化文本基础:变量声明、数据类型、运算符、表达式与赋值语句的编写
ST(Structured Text,结构化文本)是IEC 61131-3标准中语法最接近高级编程语言(如Pascal、C)的PLC编程语言。它不像梯形图那样强调电气回路的视觉逻辑,而是通过清晰的语句结构、严格的数据类型和灵活的表达式来构建控制算法。对于从事工业自动化开发的工程师而言,ST语言在数据处理、数学运算、复杂流程控制以及算法实现方面具有无可替代的优势。本章将围绕ST语言的四大核心基础——变量声明、数据类型、运算符与表达式、赋值语句——展开系统讲解,帮助你在Codesys环境中快速建立扎实的ST编程功底。
上图展示了ST语言基础知识的整体架构。变量声明是数据的容器定义,数据类型决定了数据的存储方式与取值范围,运算符与表达式构成了数据处理的核心逻辑,而赋值语句则是将计算结果写入变量的桥梁。这四者环环相扣,共同构成了ST编程的最小闭环。下面我们将逐一深入剖析。
4.1 变量声明:从内存分配到作用域控制
核心原理:在ST语言中,变量声明不仅是为数据分配内存空间,更重要的是通过关键字定义变量的作用域(局部/全局)、存储属性(保持/非保持)以及访问权限(输入/输出/内部)。Codesys遵循IEC 61131-3标准,提供了丰富的声明区关键字。
| 声明关键字 | 作用域 | 典型用途 | 示例 |
|---|---|---|---|
| VAR | POU内部局部变量 | 临时计算、中间结果 | 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中声明变量时,应遵循以下步骤:
- 在POU(程序组织单元)编辑区顶部,根据变量用途选择正确的声明区关键字。
- 为变量指定合法的标识符(以字母或下划线开头,不能包含空格和特殊字符)。
- 明确数据类型,必要时添加初始值(如
VAR speed : REAL := 100.0; END_VAR)。 - 对于需要掉电保持的数据,使用
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数据类型,并扩展了部分自定义类型。
| 类别 | 类型 | 位宽 | 取值范围 | 典型应用 |
|---|---|---|---|---|
| 布尔 | BOOL | 1位 | TRUE / FALSE | 状态标志、联锁条件 |
| 整数 | INT | 16位 | -32768 ~ 32767 | 计数器、索引 |
| 整数 | DINT | 32位 | -2^31 ~ 2^31-1 | 大范围计数 |
| 浮点 | REAL | 32位 | ±3.4E38 | 模拟量、PID计算 |
| 浮点 | LREAL | 64位 | ±1.7E308 | 高精度计算 |
| 时间 | TIME | 32位 | 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 | 非 | 最低 |
操作流程:编写表达式时,建议遵循以下步骤:
- 明确表达式的目标输出类型(BOOL、数值等)。
- 将复杂表达式拆分为多个中间变量,提高可读性。
- 使用括号明确运算顺序,避免依赖默认优先级。
- 注意短路求值:
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),构建更复杂的控制流程。