本文是CSDN上看到的一篇质量比较高的文章,自己仔细读了几遍收获很大,值得一起学习。我在作者的基础上重新排版添加了一些备注和修改了一些错误的地方。由于字数比较多,因此分成了上下篇。 本人有500人纯技术交流群,需要的话可以加我微信拉你入群:Flyzhang46 一、前言本文将会讲解高度抽象的设计模式,设计模式与案例无关,并不以案例讲题。反正学校按这种方式教了那么久也没人听得懂。我将主要以理论为主,避免与具体案例绑定,以防止读者先入为主,以为某一设计模式只能适用于某案例,或某一设计模式只能单独使用,不能结合其它设计模式,又或者某一案例只适合某一设计模式。 快捷键:
简单程序 Y0 := TRUE; 为什么要用K开头呢?K在PLC符号中代表后面的文本将作为十进制数字使用,然而数字不能用于标识符的第一个字母,这是所有编程语言的通例。K1是指4个连续端口。为什么是4个?1位16进制数代表4个端口。这个K1是指“1位16进制数”的意思,也就是4个开关量。如果改为K2,就是“2位16进制数”,代表8个开关量。Y1表示从Y1端口开始计数,实际上就是C语言里的起始指针,数组指针之类的含义。 三菱ST编程相对西门子更简单,因为它可以直接使用X、Y、M、D这几个系统标识,而西门子变量和端口全部都要声明,然后定义到指定地址才能使用。 二、结构化文本入门PLC的经典用法就是串并联逻辑电路,ST语言的串联用AND操作符,并联用OR操作符,动断触点(常闭)用NOT操作符,此外还支持奇校验XOR操作符。 2.1 单按钮
2.2 起保停X0为通时Y0设置为通,X1为通时Y0设置为断,自锁电路。 Y0 := NOT X1 AND (X0 OR Y0); 在梯形图中,有一种专业的自锁电路的替代方法,就是SET和RST指令。它们在ST中被封装成系统宏函数。
这是推荐使用的方法,简单易懂。ST宏函数和系统功能块非常多,我们能够记住一些指令就很不容易了,何况它们还有不同的参数。GX Work2提供了一个快捷键,Ctrl + F1,把插入点定位在写好的函数名上,按Ctrl + F1,IDE会自动插入参数提示。如果连函数名也不记得了,可以在右边的窗口双击插入函数名或功能块名。西门子Portal则是从左边的自定义程序和右边的系统程序中拖拽到工作区。系统函数的第一个形参都是使能标志,相当于每一个系统函数内置了一个条件表达式,只有当第一个形参传入TRUE(通)的时候,才执行指令的功能。 2.3 XOR高电平奇校验Y0 := X0 XOR X1 XOR X2;//做一个三联开关,X0,X1,X2的状态变化都会引起Y0翻转。 这个程序在X0,X1,X2之中任意一个改变状态时,都会使Y0状态变化,也就是任意一个开关都可以自由地操作灯的亮灭。这个表达式如果要用标准的串并联梯形图来做,会非常麻烦。
我们做逻辑运算多用的是高电平奇校验公式,很少用到低电平奇校验公式。当奇校验公式中有奇数个常量目标电平时,根据奇校验的算法,可以证明它等价于偶校验,其实也等于在中间的某个位置加入一个NOT运算符或对最终结果取反。 了解了奇校验的特点后,我们也可以用一个计数器来代替奇校验公式。 2.4 上升沿和下降沿ST中的上升沿检测使用LDP,下降沿使用LDF。升级版的单按钮控制:
LDP的第一个形参还是使能的意思,几乎所有的指令都有很大概率在第一个形参写TRUE,因为三菱PLC所有的指令都需要使能,而多数情况下,这些指令是需要永久使能的。LDP的第二个形参是上升沿检测的变量,这里检测的是X0的上升沿。实际上对应单片机内部电路,X0的引脚可能是收到了下降沿,这个LDP是指的从断到通的状态,与单片机电平方向无关。当收到上升沿的时候,LDP返回一个扫描周期的TRUE,TRUE与XOR组合,就等价于一个NOT,就将Y0翻转了,而LDP只返回一个扫描周期的TRUE,所以也只有这一个扫描周期的XOR等价于NOT,其余扫描周期则为XOR FALSE,也就是不起作用。这样就实现了X0在从断到通时Y0会发生状态翻转,也就是记忆按钮的效果。 2.5 定时器和计数器定时器
计数器
扩展AB相编码器的ST写法扩展阅读https://blog.csdn.net/rediculous/article/details/102656817注意:ST语言不能直接写C251
ST编写AB相编码器
第一个参数是使能C251,当它为TRUE时,X0和X1被指定用于C251,这是PLC内部系统的设计,无法更改。第二个参数如果是CC251,表示使用C251,如果是CC252就使用C252。
第三个参数是CS251的阀值。即 梯形图剩下的功能就只有定时器和计数器了。下面演示一下定时器和计数器的用法。这个程序功能为按下X0两次后,Y0输出1秒的通,然后变回断。 OUT_C(X0, CC0, 2);(* 对X0计数,它是边沿有效的,计数器C0,CC0是C0的线圈,第2个C代表'Coin' *) 三、语句3.1 条件分支IF-THEN…ELSE_IF-THEN…ELSE…END_IF;我们再来试试自锁电路的一种标准化写法,它同样具有很好的可读性。
比起SET和RST,使用了条件分支使程序看起来更像是说明文档。它的大意是:“如果X0通了,则让Y0也通,如果X0没通,但是X1通了,就让Y0断开,如果以上条件都不满足,就什么也不做,保持之前的状态。” 再来一个自锁(X0,X1)+强制点动(X2)+翻转(X3)的综合型开关电路,动力输出设计为Y4,并且每当按下按钮时,会有对应的指示灯亮起,指示灯设计Yn对应Xn: K1Y0 := K1X0;(* 4路指示灯直接赋值 *) 读者可以自己试试用梯形图串并联方式实现这个电路,一个简单的功能做成梯形图也会非常复杂。条件分支的完整模板为:
3.2 状态分支CASE-OF 1: … 2: … 3: … n: … ELSE … END_CASE;这种分支结构是专门用于状态变量的,需要使用数字作为状态变量,但代码中不一定要按大小顺序排版,也不一定要连续。未显式定义的数字会转接到ELSE段中。做一个演示用的红绿灯,有红亮(Y0)、黄亮(Y1)、绿亮(Y2)三种状态,用一个按钮X0来控制。这个程序并不十分适合这一场景,只是做为介绍语法之用,具体工程中只需要5~6行代码就搞定了。 IF LDP(TRUE, X0) THEN 与C语言家族不同,结构化文本不需要break,它不会从一个状态直接就执行到下一个状态。case语句的结构很简单,开头CASE和OF中间只能写一个数值变量,后面是常量标签加个冒号,一个ELSE代表未定义的数值,最后以END_CASE;结尾,注意那个分号。简化的写法,通过条件判断来赋值:
还有依次传递状态 (不推荐) IF LDP(TRUE, X0) THEN 个人比较推荐6行写法,比较正规,5行写法太作了,可读性不好。目前看来CASE语句好像没什么用。事实上CASE语句是IF语句的定制化版本,适合范围更窄,但能少写一些代码。接下来的设计模式中如果条件允许,用CASE会有更好的可读性,因为不重要的部分(标签数字)不会太显眼。 3.3 循环
while x0 then
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的函数或关键字。 文章来源:https://blog.csdn.net/rediculous/article/details/103624416?spm=1001.2014.3001.5502 |
|