前言
本文将以一些工作中遇到的小项目来讲解结构化文本程序基本语法,因此文章形式将是持续更新的过程,直到认为本文已达到一定水平再停止更新。本文以三菱FX5U32-M/ES这款PLC为例,开发环境为GXwork3进行讲解。
一、IO控制
本章将涉及IO信号采集与IO信号输出,信号采集将以外部开关信号讲解,信号输出将以控制外部灯组进行讲解。
1、新建ST程序
2、IO输出接线方式
假设我有一个灯组,灯组的公共端为in_com,输出端分别为line1和line2,FX5U-32M/ES外部的接线方式应该如图所示,其中负载为灯组:
3、IO输入接线方式
假设我有一组按键开关,按键的公共端为out_com,按键分别标记为out1、out2和out3,FX5U-32M/ES外部的接线方式应该如图所示,其中X0为PLC的采集点
4、编写控制外部灯组程序
以下是三个经典灯控电路,我们以此来学习一下语法:
开关电路:某个寄存器为1则开灯,为0则关灯
断电延时电路:某个寄存器为1则开灯,为0,则延时n秒关灯,类似房卡
闪烁电路:寄存器1为1则闪烁,寄存器2为1则停止闪烁
操作逻辑:先通过D0筛选控灯模式,在通过M0~M4进行控灯
Y0 := light1; // 将变量赋值给Y0,这样相当于重命名Y0为light1,我们只需要操作light1就可以间接操作Y0,方便代码阅读
model := D0; // 闪烁电路:1 、断电延时电路:2 、开关电路:3
CASE model OF
1 :
/*闪烁电路*/
SET(M1, M0);
RST(M2, M0);
light1 := M0 & NOT TS0;
OUT_T(M0, TC0, 10);
OUT_T(TS0, TC1, 50);
RST(TS1, T0);
2 :
(*断电延时电路*)
SET(M3, light1);
OUT_T(NOT M3, TC2, 50);
RST(TS2, light1);
3 :
//开关电路
IF M4 THEN
light1 := 1 ;
ELSE
light1 := 0 ;
END_IF;
ELSE
light1 := 1; //直接赋值控制灯常亮
END_CASE;
(1)赋值语句
:=
左边是变量,右边是值,如 Y0 := light1; 表示将变量light1的值赋给Y0,之所以这样写,是为了让Y0有个别名light1,这样可以使代码更清晰。
(2)case语句
CASE ?ANY_INT? OF
?值1? :
?执行语句? ;
?值2? :
?执行语句? ;
?值3? :
?执行语句? ;
ELSE
?执行语句? ;
END_CASE;
控制流语句的一种,用于选择,当满足条件时将执行之后的语句,语法上需要注意ELSE表示其他条件。
(3)结束语句
;
每当写完一条语句,则需要用分号来结束这个语句。
(4)SET指令
SET( ?BOOL_EN? , ?ANY_BOOL_d? );
如 SET(M1, M0); 当M1为1时,M0将被置位。
(5)RST指令
RST( ?BOOL_EN? , ?ANY_ELEMENTARY_d? );
如 RST(M2, M0); 当M2为1时,M0将被复位。
(6)OUT指令
OUT_T(M0, TC0, 10); 表示当M0置位,TC0定时器计时1秒
OUT_T(TS0, TC1, 50); 表示当TC0计时完成,TS0置位,TC1计时5秒
其中,TC0表示TC定时器0,TS0表示TC定时器0完成了计时后置位。
(7)按位与
&
两个位之间的运算,如果1&1则为真,1&0则为假,以此类推。light1 := M0 & NOT TS0; 表示开启M0后,假设TC0 还未计时完成,则灯常亮,完成之后TS0置位就灭掉。
(8)条件语句
IF ?条件式? THEN
?执行语句? ;
ELSE
?执行语句? ;
END_IF;
条件式为真则执行then语句,反之执行else语句。
(9)定义局部变量
只有在标签中定义才能被使用。
(10)编译
这里编译有警告,表明咋们写的程序可能有逻辑问题,这个提示代表light1被多次赋值了,可能会有问题。
5、编写按键输入程序
以下是两个按键的模拟程序,可以将M0、M1对应修改为key1、key2,统计的是2个按键的输入,如果输入不一致,则报错,需要手动设置M2来恢复环境。
key1 := X0;
key2 := X1;
key3 := X2;
// 按键计数
OUT_C(M0, CC0, K10);
count1 := WORD_TO_INT(C0);
OUT_C(M1, CC1, K10);
count2 := WORD_TO_INT(C1);
// 次数相差结果
result := ABS(count1 - count2);
// 两次结果不一致,则告警
IF result > 0 THEN
Y0 := 1; // 告警灯亮
END_IF;
// 手动恢复环境
IF M2 THEN
Y0 := 0; // 告警灯灭
RST(TRUE, CN0); // 重新计数
RST(TRUE, CN1);
M2 := 0; //
END_IF;
// 重新计数
RST(CS0, CN0);
RST(CS1, CN1);
(1)计数器指令与字节转整数指令
OUT_C(M0, CC0, K10);
count1 := WORD_TO_INT(C0);
RST(CS0, CN0);
这段代码表示计数10次,M0上升沿时计数一次,CC0加1;其实CC0就是C0,属于特殊寄存器,存储的数据为字,因此需要WORD_TO_INT来转换成整型,当10次到达之后,特殊寄存器CS0置位,使用RST来复位CN0,即可复位整个计数器。
(2)绝对值指令
result := ABS(count1 - count2);
ABS可以获得绝对值。
(3)IF另一种用法
IF result > 0 THEN
Y0 := 1; // 告警灯亮
END_IF;
可以省略 ELSE。