IEC的PLC编程语言标准(IEC61131–3) 中有5种编程语言:
1)顺序功能图(Sequential function chart) ;
2)梯形图(Ladder diagram);
3)功能块图(Function block diagram);
4)指令表(Instruction list);
5)结构文本(Structured text)。
其中的顺序功能图(SFC)、梯形图(LD)和功能块图(FBD)是图形编程语言,指令表(IL)和结构文本(ST)是文字语言。
1、简介
结构文本是一种高级语言,如果你知道如何使用高级语言来编程,像:Basic、Pascal或C,那么你会很轻松的掌握Structured Text(ST)编程;如果不知道,你会看到ST有着简单、标准的结构,保证程序高效、快速运行并简单易懂。
2、结构化文本的特点
2.1 概述
ST是针对自动化系统的高级文本编程语言。简单的标准结构确保快速、高效的编程。ST使用了高级语言的许多传统特性,包括:变量、操作符和控制流程语句。ST还能与其它的PLC编程语言一起工作。那么什么是结构文本呢?”结构”是指高水平的结构化编程能力,象一个”结构化的编程”;”文本”是指应用文本而不是梯形图和顺序函功能表的能力。 ST语言不能代替其它的语言,每种语言都有它自己的优点和缺点。ST主要的一个优点就是能简化复杂的数学方程。
2.2 特点
结构化文本有以下特点: 高级文本编程语言结构化的编程简单的标准结构快速高效的编程使用直观灵活;与PASCAL类似;有计算机编程经验的人可以很容易地使用它;符合IEC标准。
3、结构文本基础
3.1 表达式
表达式是指返回变量评估值的结构。表达式由操作符和操作数组成。操作数可以是变量,常量,调用函数或其他表达式。
3.2 赋值操作符
通过一个表达式和一个值来给变量赋值。赋值语句包括位于左边的变量,赋值操作符”:=”,及后边需要计算的表达式。所有的语句,包括赋值语句,必须要以分号”;”结尾。
3.3 注释
虽然注释经常被删掉,但它们是源代码中非常重要的一部分。它们解释了一部分代码,使程序更易读懂。注释帮助你或其他人读你的程序,即使过去了很长时间。注释不被编译,因此不会影响程序的执行。注释应该用一对星号和小括号括起来。
3.4 操作符优先级
如果在一个表达式中使用几个操作符,就会出现优先级的问题(执行的顺序)。操作符按优先级的顺序来执行。在任何一个表达式中,首先执行最高级别的操作符,接着执行低一级的操作符,等等,直到执行完所有的操作符。具有相同级别的操作符按照书写顺序从左至右依次执行。
4、命令组
ST有下面的命令组: 布尔逻辑操作算术操作比较
操作判断
Case语句
4.1 布尔逻辑操作操作数不需要是BOOL类型。布尔逻辑操作:
符号 | 逻辑操作 | 例子 |
NOT | 取反 | a := NOT b; |
AND | 逻辑与 | a := b AND c; |
OR | 逻辑或 | a := b OR c; |
XOR | 异或 | a := b XOR c; |
这些操作符可以形成一个逻辑表达式和条件语句,结果是真(TRUE)或假(FALSE)。
4.2 算术运算使用高级语言的决定性因素是看它处理算术运算的简单程度。
4.2.1 基本的算术运算
ST为应用程序提供了以下基本的算术运算:
符号 | 算术操作 | 例子 |
:= | 赋值 | a := b; |
+ | 加 | a := b + c; |
– | 减 | a := b – c; |
* | 乘 | a := b * c; |
/ | 除 | a := b / c; |
MOD | 取模 (显示余数) | a := b mod c; |
数据类型是非常重要的参数。看下面的表格。:
语法 | 数据类型 | 结果 | ||
Res | Op | Op | ||
Res := / ; | INT | INT | INT | |
Res := / ; | REAL | INT | INT | .0 |
Res := .0 / ; | REAL | REAL | INT | . |
Res := .0 / ; | INT | REAL | INT | Error |
可以看到,结果也依赖于语法和数据类型。表达式左边的数据类型应该等同于(或大于)右边的数据类型。
4.2.2 隐性数据类型转换
该类型的转换由编译器完成。编译器将表达式中低的数据类型转换成高的数据类型。如果有两种或多个类型的变量参与运算,那么必须将它们转换成相同的类型以便执行运算。
Data type | BOOL | SINT | INT | DINT | USINT | UINT | UDINT | REAL |
BOOL | BOOL | x | x | x | x | x | x | x |
SINT | x | INT | DINT | USINT | UINT | UDINT | REAL | |
INT | x | INT | DINT | INT | UINT | UDINT | REAL | |
DINT | x | DINT | DINT | DINT | UDINT | UDINT | REAL | |
USINT | x | USINT | INT | DINT | UINT | UDINT | REAL | |
UINT | x | UINT | UINT | DINT | UINT | UDINT | REAL | |
UDINT | x | UDINT | UDINT | UDINT | UDINT | UDINT | REAL | |
REAL | x | REAL | REAL | REAL | REAL | REAL | REAL |

4.2.3 显性数据类型转换
显性数据类型转换也是数据类型转换问题。我们知道,表达式的左右两边要有相同数据类型,还需注意不可超出数据范围。
4.3 比较操作
高级编程语言ST或以允许比较操作的简单结构分枝。比较的结果是真(TRUE)或假(FALSE)。
符号 | 逻辑比较含义 | 例子 |
= | 等于 | IF a = b THEN |
<> | 不等于 | IF a <> b THEN |
> | 大于 | IF a > b THEN |
>= | 大于等于 | IF a >= b THEN |
< | 小于 | IF a < b THEN |
<= | 小于等于 | IF a <= b THEN |
比较操作作为一个逻辑条件用在IF, ELSE, WHILE 和UNTIL语句中。
4.4 判断
用IF语句表示判断,这里还要用到比较操作。判断分三部分:
简单IF语句
IF – ELSE语句
IF – ELSIF语句嵌套的IF
判断 | 语法 | 描述 |
IF THEN | IF a > b THEN | 1. 比较 |
Result := 1; | 1. 语句(s) | |
ELSIF THEN | ELSIF a > c THEN | 2. 比较 (可选) |
Result := 2; | 2. 语句(s) | |
ELSE | ELSE | 前面IF语句都不满足(可选) |
Result : = 3; | 3. 语句(s) | |
END_IF | END_IF | 判断结束 |
4.4.1 IF
最简单的IF判断语句。基本上,如果条件表达式的结果为TRUE就执行语句。如果条件表达式的结果是 FALSE,程序就执行END_IF后面的语句。条件表达式可以是简单关联的语句或用运算符(and,or等)连接的复合语句。
4.4.2 ELSE
它是简单IF语句的扩展。在IF结构中应该只有一个ELSE。如果条件为TRUE,执行语句A。如果条件为FALSE,执行语句B。
4.4.3 ELSIF
运用一个或多个ELSE_IF语句可以实现多个不同的条件,而不用使用多个简单的IF语句。

处理器自上而下地执行判定。如果条件的结果为TRUE,那么就执行属于这个条件的指令和命令,之后处理器就跳到判断语句的结尾(END_IF)。在程序的一次循环中,无论下一个条件是否为TRUE,只有上面属于第一个条件TRUE的语句被执行。如果IF或ELSIF条件都不为TRUE,那么就执行属于ELSE下的指令。
4.4.4 嵌套的IF语句
嵌套对于依赖其它条件的条件测试很有用处。一个嵌套的IF语句其优先级低于上一层的优先级,它的执行取决于上一层IF条件的结果。使用嵌套时必须注意每个IF要和END_IF相匹配,否则会导致错误的执行顺序。

建议在每个嵌套的IF 语句和它的执行语句中使用缩排。IF语句可以嵌套在你想要的深度,但是三十或四十级以后,编辑器会用完内存,所以丢失了代码的总貌。当使用嵌套多于级或级时,应该重组程序代码。
用两个但并不嵌套的IF语句也可以达到同样的功能,就像嵌套的语句一样。可以在多个语句中运用标识变量或一个标志。第一个IF语句描述该标志,其他的IF语句利用该变量。

在这种情况下,IF语句有相同的优先级,第二个IF语句和第一个IF语句一样每次都执行。不用相同的变量,可以有两个独立的IF语句。当发生以下情况时,推荐使用Case语句代替IF语句: IF结构有过多分层使用过多(三个或更多)的ELSE_IF。
在这种情况下Case语句更容易读懂。CASE与IF结构相比较还具有另一个优点:CASE语句中只做一次计算,并能创建更有效的代码。
4.5 Case 语句
在CASE语句中,控制变量与几个值作比较,如果表达式的结果与其中一个值相同,那么就执行相应的语句。如果表达式的结果与任何一个值都不相同,那么就执行象IF 语句一样的ELSE分支。语句执行完后,继续执行END_CASE后的程序。
关键字 | 语法 | 描述 |
CASE OF | CASE step variable OF | CASE开始 |
,: Display := MATERIAL | 从 到 | |
: Display := TEMP | ||
,,..0: Display := OPERATION | ,,,,,,0 | |
END_CASE | END_CASE | CASE结束 |

在程序的一次循环中,只执行case的一个子句。

备注: 在CASE 语句步骤中可以用常量来代替数字。这样可以更加容易读程序。
CASE语句的语法:
CASE语句以CASE开始,以END_CASE结束,并且各自单独占一行。在CASE和OF之间的变量必须是UINT类型。在CASE的子句中,只能使用正整数,不允许使用变量名或表达式。数字不能重叠使或在几个区域内使用。
4.6 循环语句
在很多应用程序中,需要多次执行某些步骤,这就是重复执行代码的原因,这个过程叫循环。循环程序的设计中需要建立这样一种程序使它能够循环返回并循环执行自身程序。
循环语句使源代码简短并一目了然。循环语句可以嵌套在其它语句中。循环程序编写时很容易进入死循环,一直重复执行自身程序,引起控制器启动看门狗限制,并产生一个严重错误阻碍程序的执行。因此,通常使用一些方法来跳出循环:设定循环次数或条件改变时停止循环。在ST中有几种不同的循环方式:
有限制的:FOR
无限制的:WHILE,REPEAT
4.6.1 FOR
如果提前可以确定循环的次数就用FOR语句,否则就用WHILE 或REPEAT。
关键字 | 语法 | 描述 |
FOR TO BY DO | FOR i:=StartVal TO StopVal {BY Step} DO | {}中的部分是可选的 |
Res := value + ; | 循环语句段 | |
END_FOR | END_FOR | FOR语句结束 |

FOR语句可以递增或递减循环控制变量的值,使它从起始值到达终止值。递增或递减的默认值为。
每次循环之前都会检测终止条件,如果循环控制变量的值超过终止值时,就不再执行语句段了。
4.6.2 WHILE
WHILE循环除了条件可以是任意的布尔表达式以外其他和FOR循环用处一样。当条件满足时,执行循环语句。当逻辑条件为TRUE就重复调用语句时,使用WHILE语句。
关键字 | 语法 | 描述 |
WHILE DO | WHILE i< DO | 布尔条件 |
Res := value + ; | 语句 | |
i := i + ; | 语句 | |
END_ WHILE | END_ WHILE | WHILE结束 |

语句一直执行直到UNTIL条件为TRUE。如果UNTIL条件在第一次执行时为TRUE,那么语句只执行一次。
备注: 如果UNTIL条件永远不为TRUE,那么程序进入死循环,并产生一个运行错误。
4.6.4 EXIT
EXIT语句是当终止条件满足时,退出所有的循环语句。


4.7 调用功能块
ST中调用功能块的方法:写出功能块的名称,并在括号中给的需的输入参数分配变量名。
在调用功能块之前,需要给输入参数分配所需的值。功能块调用放在一行里,以分号结束,在调用功能块之后才能读取FB的输出值。

首先是功能块的名称,接着是位于括号里的输入参数。输入参数用逗号隔开。功能块调用以分号结束。
4.8 指针和动态变量
使用这些是可选的。在运行时,系统给动态变量PV分配了一个内存地址,这个过程叫做动态变量的寻参或初始化。当一个动态变量被初始化后,根据数据类型它可以获得它所指向的存储器的内容。 用ADR()操作符,返回的是小括号中变量的地址,为UDINT类型。这行语句应该以分号“;”结束。

附录
关键字是ST可用的语句,但不能作为变量名。Automation Studio编辑器用蓝色来显示它们。
关键字 | 描述 |
ACCESS | 使用动态变量。 |
BIT_CLR | A := BIT_CLR(IN, POS) A为变量IN在POS 位清0后的值。IN 值保持不变。 |
BIT_SET | A := BIT_CLR(IN, POS) A为变量IN在POS 位置后的值。IN 值保持不变。 |
BIT_TST | A := BIT_TST(IN, POS) 位的状态值。 A为IN变量在POS位的状态值。 |
BY | 参考FOR 语句。 |
CASE | 参考CASE语句。 |
DO | 参考 WHILE语句。 |
EDGE | 检测上升沿和下降沿信号。 |
EDGENEG | 检测上升沿信号。 |
EDGEPOS | 检测下降沿信号。 |
ELSE | 参考IF语句。 |
ELSIF | 参考 IF语句。 |
END_CASE | 参考 CASE语句。 |
END_FOR | 参考 FOR语句。 |
END_IF | 参考 IF语句。 |
END_REPEAT | 参考 REPEAT语句。 |
END_WHILE | 参考 WHILE语句。 |
EXIT | 参考 EXIT语句。 |
FOR | 参考 FOR语句。 |
IF | 参考 IF语句。 |
REPEAT | 参考 REPEAT语句。 |
RETURN | 可以通过例子中的条件来结束函数。 |
THEN | 参考 IF语句。 |
TO | 参考 FOR语句。 |
UNTIL | 参考 REPEAT语句。 |
WHILE | 参考 WHILE语句。 |
在结构文本中使用有些函数不需插入库函数。Automation Studio编辑器用蓝色显示这些函数。
函数 | 例子 |
ABS | 返回数的绝对值。 ABS(-) 返回 。 |
ACOS | 返回数的arc cosine值。(cosine的反函数)。 |
ADR | 返回变量的地址。 |
AND | 位操作逻辑与。 |
ASIN | 返回数的arc sine值。(sine的反函数)。 |
ASR | 操作数算术右移: A := ASR (IN, N) IN 右移N位, 左边由符号位填充。 |
ATAN | 返回数的arc tangent值。(tangent的反函数)。 |
COS | 返回数的cosine值。 |
EXP | 指数函数: A := EXP (IN). |
EXPT | 一个操作数为另一个操作数的幂: A := EXPT (IN, IN). |
LIMIT | A = LIMIT (MIN, IN, MAX) MIN 是结果的下限, MAX是结果的上限。如果IN小于MIN,则返回结果是 MIN。如果IN大于MAX,则返回结果是MAX。否则,返回结果为IN。 |
LN | 返回数的自然对数。 |
LOG | 返回以0为底的数的对数。 |
MAX | 最大值函数。返回两个数中较大的数。 |
MIN | 最小值函数。返回两个数中较小的数。 |
MOD | 将USINT, SINT, INT, UINT, UDINT, DINT 变量取模除另一个这些类型的变量。 |
MOVE | 把输入变量复制到输出变量。:=符号用有赋值语句中。 “A := B;” 和 “A := MOVE (B)相同;” |
MUX | 选择: A = MUX (CHOICE, IN, IN, … INX); CHOICE指定返回哪个操作数(IN, IN, … INX)。 |
NOT | 位取反。 |
OR | 位操作逻辑或。 |
ROL | 循环左移操作数: A := ROL(IN, N); IN中每位左移N次,最左面的位移到右边。 |
ROR | 循环右移操作数: A := ROL(IN, N); IN中每位右移N次,最右面的位移到左边。 |
SEL | 二进制选择: A := SEL (CHOICE, IN, IN) CHOICE必须是BOOL类型。如果CHOICE为FALSE,那返回IN,否则返回 IN。 |
SHL | 操作数的位左移: A := SHL (IN, N); IN 左移 N 位, 右边的位以零填充。 |
SHR | 操作数的位右移: A := SHR (IN, N); IN 右移 N 位, 左边的位以零填充。 |
SIN | 返回数的sine值。 |
sizeof | 以字节数返回指定变量的长度。 |
SQRT | 返回数的平方根。 |
TAN | 返回数的tangent值。 |
TRUNC | 返回数的整数部分。 |
XOR | 位操作逻辑异或 |