SIEMENS西门子吉林省延边朝鲜族自治州(授权)伺服电机一级代理商——西门子东北总代理
| 更新时间 2024-11-26 07:00:00 价格 请来电询价 西门子总代理 PLC 西门子一级代 驱动 西门子代理商 伺服电机 联系电话 15903418770 联系手机 15915421161 联系人 张经理 立即询价 |
我们再来试试自锁电路的一种标准化写法,它同样具有很好的可读性。
IF X0 THENY0 := TRUE;
ELSE_IF X1 THEN
Y0 := FALSE;
END_IF;(* 注意:这个END_IF是要加分号结尾的,ST语言坑死人,多少新手被坑在这里好久才发现突然需要一个分号 *)
比起SET和RST,使用了条件分支使程序看起来更像是说明文档。它的大意是:“如果X0通了,则让Y0也通,如果X0没通,但是X1通了,就让Y0断开,如果以上条件都不满足,就什么也不做,保持之前的状态。” 再来一个自锁(X0,X1)+强制点动(X2)+翻转(X3)的综合型开关电路,动力输出设计为Y4,并且每当按下按钮时,会有对应的指示灯亮起,指示灯设计Yn对应Xn:
K1Y0 := K1X0;(* 4路指示灯直接赋值 *)IF X0 THEN
Y4 := TRUE;(* 启动 *)
ELSE_IF X1 THEN
Y4 := FALSE;(* 停止 *)
ELSE_IF LDP(TRUE, X3) THEN
Y4 := NOT Y4;(* 翻转 *)
ELSE_IF LDP(TRUE, X2) OR LDF(TRUE, X2) THEN
Y4 := X2;(* X2动作时,取消记忆,强制变为手动 *)
END_IF;(* 再次强调:这个END_IF是要加分号结尾的,ST语言坑死人,多少新手被坑在这里好久才发现突然需要一个分号 *)
读者可以自己试试用梯形图串并联方式实现这个电路,一个简单的功能做成梯形图也会非常复杂。条件分支的完整模板为:
IF conditions THENtasks;(* 语法上IF语句任何一段分支的tasks都可以是空的。如果是空的,分号也可以不要 *)
ELSE_IF conditions THEN (* 如果没有其它条件,ELSE_IF必须省略,如果有多个,ELSE_IF应当有很多,语法上没有上限,可以写到程序存储器不够了为止 *)
tasks;
ELSE_IF conditions THEN
tasks;
...
ELSE (* 如果没有默认操作,ELSE可以省略,也可以不省略 *)
tasks;
END_IF;(* 这个地方破天荒地有一个分号 *)
3.2 状态分支CASE-OF 1: … 2: … 3: … n: … ELSE … END_CASE;
这种分支结构是专门用于状态变量的,需要使用数字作为状态变量,但代码中不一定要按大小顺序排版,也不一定要连续。未显式定义的数字会转接到ELSE段中。做一个演示用的红绿灯,有红亮(Y0)、黄亮(Y1)、绿亮(Y2)三种状态,用一个按钮X0来控制。这个程序并不十分适合这一场景,只是做为介绍语法之用,具体工程中只需要5~6行代码就搞定了。
IF LDP(TRUE, X0) THEND0 := D0 + 1;(* 状态变量如果无止境地加上去会怎么样?事实上不会,因为在CASE里有做限制 *)
END_IF;
CASE D0 OF
0:(* 状态0的时候Y0通。不一定要换行,只是为了写注释方便我在冒号后面直接换行了*)
Y0 := TRUE;
Y1 := FALSE;
Y2 := FALSE;
1:(* 状态1时Y1通 *)
Y0 := FALSE;
Y1 := TRUE;
Y2 := FALSE;
2:(* 状态2时Y2通*)
Y0 := FALSE;
Y1 := FALSE;
Y2 := TRUE;
ELSE(* 其它状态时,跳到状态0 *)
D0 := 0;
END_CASE;
与C语言家族不同,结构化文本不需要break,它不会从一个状态直接就执行到下一个状态。case语句的结构很简单,开头CASE和OF中间只能写一个数值变量,后面是常量标签加个冒号,一个ELSE代表未定义的数值,Zui后以END_CASE;结尾,注意那个分号。简化的写法,通过条件判断来赋值:
IF LDP(TRUE, X0) THEND0 := (D0 + 1) MOD 3;
END_IF;
Y0 := D0 = 0;
Y1 := D0 = 1;
Y2 := D0 = 2;
还有依次传递状态 (不推荐)
IF LDP(TRUE, X0) THENY2 := Y1;
Y1 := Y0;
END_IF;
Y0 := NOT (Y1 OR Y2);
个人比较推荐6行写法,比较正规,5行写法太作了,可读性不好。目前看来CASE语句好像没什么用。事实上CASE语句是IF语句的定制化版本,适合范围更窄,但能少写一些代码。接下来的设计模式中如果条件允许,用CASE会有更好的可读性,因为不重要的部分(标签数字)不会太显眼。
3.3 循环FOR temp := 起始值 TO 完成值 BY 增量 DO业务代码
END_FOR;
while x0 then
y0 := 1;
end_while;
REPEAT
D0 := D0 + 1;
UNTIL D0 == 0 END_REPEAT;
3.4 跳转指令
提前终止当前循环,进入尾部的代码,相当于C的 break。
提前跳过本次循环,进入首部的代码,与C的continue类似。但三菱GX Works2中没有这个关键字。
返回,相当于X86汇编的RET指令,RETURN是无操作数指令。ST的函数返回值直接函数名接受值。三菱FX3U的函数是一次性的,建议不要将自定义函数用于FX3U。造成三菱FX3U函数为一次性的原因是FX3U没有动态栈。能够函数复用的X86软件的编译器会给每一个CALL指令前面加上硬件压栈指令PUSH,在RET之后会加上硬件弹栈指令POP。硬件栈是由CPU直接操作的连续内存空间,不是软件模拟的数据结构。它需要CPU内置有栈指针寄存器。而FX3U的PLC程序是虚拟的处理器,没有设计栈指针的功能。虽然可以用软件栈代替,但他们也没有这么做。这就导致了所有CALL命令都绑定在一块固定的寄存器上,无法嵌套。而且寄存器绑定函数后就会导致数据耦合,产生难以预料的后果。
三菱FX3U的功能块可以产生多个实例,每一个实例绑定独立的寄存器,就可以安全地做到代码复用。对于纯计算,即没有状态存储功能的函数和功能块,可以放心地复用,对于有状态存储功能的功能块需要创建多个实例。所有支持梯形图的PLC都难以实现动态栈,因为动态栈和梯形图的程序理念是相背离的,动态栈希望程序尽可能使用动态变量,而梯形图依赖于静态变量。动与静的矛盾之下,PLC设计者必须进行取舍。FX3U的内存量是足够动静共存的,问题在于动态栈很难兼容梯形图,而梯形图才是PLC的主要卖点。
跳转到指定标签位置,和X86指令同名,可以用于代码混淆,不建议手写。但三菱GX Works2中没有这个关键字。不确定是不是我的资料的问题。三菱Q系列有JMP指令(比FX系列可以节省一个LD M8000,其实没什么很大的意义),但不能作为ST的函数或关键字。