西门子SCL语言回顾复习和编写第1个面向对象程序
(形参:形参指的是指令上标记该指令要使用的数据位置的标识符;简单来说就是只有数据类型,没有实际的地址,在调用时可以写入)。
(实参:实参指的是包含指令要使用的数据的存储单元(含%数据前缀)或常量,。用户指定的实参的数据类型必须与指令指定的形参所支持的数据类型之一匹配。就是需要实际地址)
文章目录
目录
前言
一、回顾
1.数据类型
2.表达式、定时器、边沿指令、转换指令、块结构、控制指令
1.表达式
2.定时器
3.边沿指令
4.转换指令
5.块结构
6.控制指令
二、面向对象编程(一键启停功能的功能块)
1.控制要求
2.分析
3.设计
1.建立FB块和形参
2.编写
3.调用代码和效果
4.多处调用
1.多次调用(适合少量调用)
2.在函数块中嵌套调用
3.使用数组,多次调用
4.另外在背景数据块中可以清晰的看到我们所写的块。
总结
前言
经过前面编程指令和scl应用的学习,我们掌握了一些SCL语言的知识;这一章我们简单回顾一下前面学过的知识和指令,然后学习一些面向对象编程的思路和一些方法,再编写一个面向对象的程序设计 “一键启停功能块”。
一、回顾
1.数据类型
数据类型分为基本数据类型、复杂数据类型、自定义数据类型
基本数据类型:位,字节,字,双字,浮点型,双精度浮点型,整型。
数据类型 | 位大小 | 数值类型 | 数值范围 | 常数示例 | 地址示例 |
---|---|---|---|---|---|
bool | 1 | 二进制 | 2#0或2#1 | 2#0 | I1.0、Q0.1 |
byte | 8 | 无符号整数 | 0到255 | 12 | IB2 |
有符号整数 | -128到127 | -67 | IB10 | ||
16进制 | B#16#0到B#16#ff,16#0到16#ff | 16#f | DB1.DBB4 | ||
word | 16 | 无符号整数 | 0到65535 | 200 | Mw10 |
有符号整数 | -32768到32767 | -300 | DB1.DBW2 | ||
16进制 | 16#0到16#ffff | W#16#F1C0 | |||
DWord | 32 | 无符号整数 | 0到4294967295 | 234762 | MD10 |
有符号整数 | -2147483648到2147483647 | -243561 | DB1.DBD8 | ||
16进制 | 16#000000到16#ffffff | 16#B_01F6 | |||
Real | 32 | 浮点型 | -3.402823e+38到1.175495e-38 +1.175 495e-38到+3.402823e+38 | 123.456,-3.4,1.0 | MD100、DB1.DBD8 |
LReal | 64 | 双精度浮点型 | -1.7976931348623158e+308 到-2.2250738585072014e308 +0 +22250738585072014e308到 +1.7976931348623158e +308 | 12345.123456789e40、1.2E+40 | DB name.var_name规则: ·不支持直接寻 址·可在 OB、FB或FC块接口数组中进行分配 |
USInt | 8 | 无符号短整型 | 0到255 | 78,2#01001110 | MB0DB1.DBB4 |
SInt | 8 | 短整型 | -128 到 127 | +50,16#50 | |
UInt | 16 | 无符号整型 | 0到65535 | 65295,0 | MW2、DB1.DBW2 |
Int | 16 | 整型 | -32,768 到 32,767 | 30000.+30000 | |
UDInt | 32 | 无符号双整型 | 0到4294,967,295 | 4042322160 | MD6、DB1.DBD8 |
DInt | 32 | 双整型 | -2,147,483,648 到2,147,483,647 | -2131754992 |
基本数据类型:时间(定时器相关)
数据类型 | 大小 | 范围 | 常数输入示例 |
---|---|---|---|
Time | 32 | -2,147,483.648 ms 到+2,147,483,647 ms | T#5m 30sT#1d 2h 15m 30s 45ms |
Data | 16 | D#1990-1-1到D#2168-1231 | D#2009-12-31 |
Time_of_day | 32 | TOD#0:0:0.0 到TOD#23:59:59.999 | TOD#10:20:30.400 |
基本数据类型:字符型(字符相关)
数据类型 | 大小 | 范围 | 常数输入示例 |
---|---|---|---|
char | 8 | 16#00到16#FF | 'A' t, '@'a'z’ |
Wchar | 16 | 16#0000 到16#FFFF | A,t,@,a,,亚洲字符、西里尔字符以及其它字符 |
String | n+ 2字节 | n=(0到254字节) | "ABC" |
WString | n+ 2个字 | n=(0到65534个字) | ”a123@XYZ.COM" |
复杂数据类型:
数据类型 | 大小 | 范围 | 常数输入示例 |
---|---|---|---|
DTL(长格式日期和时间) | 12 | 最小: DTL#1970-01-01-00:00:00.0最大:DTL#2262-0411:23:47:16.854 775807 | DTL#2008-12-1620:30:20.250 |
Byte | 组件 | 数据类型 | 值大小 |
---|---|---|---|
0,1 | 年 | UINT | 1970到2554 |
2 | 月 | UINT | 1到12 |
3 | 日 | UINT | 1到31 |
4 | 工作日 | UINT | 1(星期日)到 7(星期六) |
5 | 小时 | UINT | 0到23 |
6 | 分 | UINT | 0到59 |
7 | 秒 | UINT | 0到59 |
8,9,10,11 | 纳秒 | UINT | 0到 999 999 999 |
数据类型 | 数组语法 | |
---|---|---|
ARRAY | 全部数组元素必须是同一数据类型。 数组可以是一维到六维数组。 用逗点字符分隔多维索引的最小最大值声明 不允许使用嵌套数组或数组的数组。 数组的存储器大小_= (一个元素的大小*数组中的元素的总数) | |
数组声明 | ARRAY[1..20] of REAL | “1维,20 个元素 |
ARRAY[1..2,3..4] of CHAR | 2维,4 个元素 | |
数组地址 | ARRAY1[0] | ARRAY1元素0 |
ARRAY2[1,2] | ARRAY2 元素[1,2] | |
ARRAY3[i,j] | 如果i=3 且i=4,则对ARRAY3的元素[3,41 进行寻址 | |
2.表达式、定时器、边沿指令、转换指令、块结构、控制指令
1.表达式
表达式有逻辑表达式、关系表达式、算术表达式。
逻辑表达式:&/and(与),OR(或),XOR(异或),NOT(取反);
关系表达式:=,>,<,<=,>=,<>,等一些;
算术表达式:+,-,*,/,%,等等。
2.定时器
关于定时器在前面说过使用方法以及简单案例,这里以TON为例记一下定时器使用技巧:
IEC定时器在调用的时候会需要指定其所对应的背景存储区,该存储区可以是专属背景DB块也可以是共享数据块中的Timer数据,也可以是FB中静态存储区中的Timer数据。
在编程的时候,不建议大家为每个定时器建立专属的背景DB块,这种方式比较浪费系统数据并且且容易混乱;
这里建议下面两种方式:
1.在OB块中使用定时器: 建立一个专用DB块,在DB块中使用数组的方式建立若干个定时器存储区
如下图:在“TECT”数据块中,分别为TON、TOF、TP定时器构建了5个定时器;
建立方法:在DB块中建立,如果是ton定时器,数据类型就是 Array[1..5] of TON_ TIME。
2.在FB块中使用定时器
选择接口模式,这样当FB块被调用的时候,由于每个FB块都需要指定背景数据块,定时器都会被自动分配新的定时器地址,可以在FB编程之前,先定义相关的定时器存储区。
如图:在块接口处的静态变量中,定义了10个定时器类型。(Array[1..10] of IEC_TIMER)
3.定时器调用
我们用前面两种方法建立好之后,就可以使用了。
如图:块接口和DB块
3.边沿指令
边沿指令是指 上升沿和下降沿,这里一样可以在FB块接口中建立,数据类型就是 R_TRIG,这里在DB块中不支持多重实例,所以建在接口处就可以了。
4.转换指令
1.隐式转换(大数据类型可以兼容小数据类型)
隐式数据类型转换处理不同数据类型的操作数,自动转换数据类型以匹配最大的数据类型不需要显式转换;
像DWORD型数据可以兼容WORD数据类型,这里会自动转换。例如:#MyDword:= #MyByte AND W#16#ff;
2.显式转换
当出现逆向的数据类型计算或者整数与浮点数之间的数据计算时,将提示错误或报警信息。此时需要显式转换。
像Word类型转换为DWORD类型时,就需要显式转换,显式转换指令是:char_TO_int(),To两边是要转换的类型,括号里面是需要转换的。如图:
5.块结构
1.模块化编程
模块化编程将复杂的自动化任务划分为对应于生产过程的技术功能的较小的子任务,每个子任务对应于一个称为“块的子程序,可以通过块与块之间的相互调用来组织程序。这样的程序易于修改、查错和调试。
块结构显著增加了PLC程序的组织透明性、可理解性和易维护性。
OB、FB、FC都包含代码,统称为代码块(Code)块
被调用的代码块又可以调用别的代码块,这种调用称为嵌套调用
在块调用中,调用者可以是各种代码块,被调用的块是OB之外的代码块。调用功能块时需要为它指定一个背景数据块。
2.FC块
功能(Function,FC)是用户编写的子程序,包含完成特定任务的程序FC调用它的块共享的输入、输出参数,执行完FC,将执行结果返回给调用它的代码块。功能(Function,FC)没有固定的存储区,功能执行结束后,其局部变量中的临时数据就丢失了。可以用全局变量来存储那些在功能执行结束后需要保存的数据。
在编程过程中,具备复用功能的FC块适合用在单扫描周期能完成的任务中,如线性转换程序,逻辑判断功能等。
3.FB块
功能块(FB)是用户编写的有自己的存储区(背景数据块)的块。FB的典型应用是执行不能在一个扫描周期结束的操作。每次调用功能块是,却需要指定一个背景数据块,背景数据块随功能块的调用而打开,在调用结束时自动关闭。功能块的输入、输出和静态变量(Static)用指定的背景数据块保存,但是不会保存临时局部变量(Temp)中的数据。功能块执行后,背景数据块中的数据不会丢失。IN复用型FB的显著特点是内部会使用上升沿、下降沿、定时器等功能指令
两者区别:
FB有自己的背景数据块,而且内部有静态变量区,可以写上升沿、下降沿、定时器等功能指令;
FC没有上面这些,执行结束后里面的局部变量就没有了;
两者各有优缺。
6.控制指令
SCL语言编程中,常用的控制指令有:if ,if else,if elsif,case of ,for 循环。比较常用的这些。
二、面向对象编程(一键启停功能的功能块)
面向对象是指对一个对象来编程(这个对象可以是电机或者其他的,我们以它为中心来进行编程)
1.控制要求
设计一个其有一键启停功能的功能块,具有以下功能:
A.一键启停模式:操作启动按钮,按一下启动,再按一下停止。
B.运行模式:按住启动按钮,延迟时间到了之后设备启动。按下停止按钮,设备立即停止。
C.模式切换后立即停机。
2.分析
根据题目要求可以看:这里要求一个一键启停控制和一个定时器延时开启以及一个模式切换功能,这里分开来说一下。
一键启停:按下启动按钮电机启动,再次按下启动电机停止,这里用梯形图和scl分别实现一下 。
梯形图:用上升沿接通Inc加计数并置位电机线圈,这是MW20为1,当再次按下启动按钮,Inc增加为2,等于2时复位线圈并把MW20清零,可以循环使用。
SCL:这里由上升沿接通,对km线圈进行一个取反来实现功能(具体如图)。
3.设计
1.建立FB块和形参
(形参:形参指的是指令上标记该指令要使用的数据位置的标识符;简单来说就是只有数据类型,没有实际的地址,在调用时可以写入)。
(实参:实参指的是包含指令要使用的数据的存储单元(含%数据前缀)或常量,。用户指定的实参的数据类型必须与指令指定的形参所支持的数据类型之一匹配。就是需要实际地址)
在FB块上方接口处,根据要求写入输入输出(这里写的就是形参)
将形参写好就可以编写了。
2.编写
A.一键启停模式:操作启动按钮,按一下启动,再按一下停止。
1.这里首先获取启动按钮上升沿和模式切换的上升下降沿;
#上升沿1(CLK := #启动按钮);
#上升沿2(CLK := #模式切换按钮);
#下降沿1(CLK := #模式切换按钮);
使用启动按钮上升沿来完成一键启停:
IF #上升沿1.Q THEN // 上升沿触发
#km电机 := NOT #km电机;//对线圈进行取反
END_IF;
B.运行模式:按住启动按钮,延迟时间到了之后设备启动。按下停止按钮,设备立即停止。
C.模式切换后立即停机。
2.这里分为一键启停和运行两种模式,模式切换按钮为0时,是一键启停,为1是运行模式(这是在定义形参时规定好的),为1时进入运行模式,当按住启动按钮一定时间后,设备启动。
#T[1].TON(IN := #模式切换按钮 & #启动按钮 & NOT #停止,
PT := #设定时间);
IF #模式切换按钮 THEN //当切换按钮为1时是运行模式
IF #T[1].Q THEN
#km电机 := 1;
END_IF;
ELSE //为0,一键启停模式
IF #上升沿1.Q THEN
#km电机 := NOT #km电机;
END_IF;
3.就是模式切换时立即停止和停止按钮,这里就用到模式切换的上升和下降沿,不管是从0变1还是从1变0,电机都会停止。
IF #停止 THEN
#km电机 := 0;
END_IF;
IF #上升沿2.Q OR #下降沿1.Q THEN
#km电机 := 0;
END_IF;
3.调用代码和效果
//获取按钮的上升沿或下降沿
#上升沿1(CLK := #启动按钮);
#上升沿2(CLK := #模式切换按钮);
#下降沿1(CLK := #模式切换按钮);
//模式切换停止,和停止按钮停止
IF #停止 THEN
#km电机 := 0;
END_IF;
IF #上升沿2.Q OR #下降沿1.Q THEN
#km电机 := 0;
END_IF;
//运行模式用到的延时定时器
#T[1].TON(IN := #模式切换按钮 & #启动按钮 & NOT #停止,
PT := #设定时间);
//判断模式切换按钮的两种情况
IF #模式切换按钮 THEN //为1时,运行模式
IF #T[1].Q THEN
#km电机 := 1;
END_IF;
ELSE //为0时,一键启停
IF #上升沿1.Q THEN
#km电机 := NOT #km电机;
END_IF;
END_IF;
代码写好后,在main(OB)中调用FB函数:两边是接口,我们写入相应的输入输出就可以啦!
输入可以是M点,方便调试。
效果:这里监视打开就可以调试了
4.多处调用
这一个功能块写好后,可能很多地方都需要调用,这里有几种方法;
1.多次调用(适合少量调用)
在OB多拉出来几个,写入不同变量就可以了
2.在函数块中嵌套调用
我们新建一个FB(M_FB)在里面调用多次FB1,最后在OB中调用1个M_FB函数块就可以了,这种比较节省空间。
3.使用数组,多次调用
当我们要调用100次或更多是,可以用数组来建立;在函数接口处建立多个。
按照下标可以调用;
4.另外在背景数据块中可以清晰的看到我们所写的块。
总结
1.调试技巧:调用块过之后,写入相应变量,可以使用 Ctrl+F2和Ctrl+F3来快速置一或置零;
2.定时器技巧:可以在FB块 静态变量中建立定时器,不容易混乱,或在DB中建立;
3.边沿指令技巧:也可以在FB静态变量中建立,DB中不兼容;
4.编程习惯:在SCL中可以使用中文或英文来命名变量,可以根据个人来选择。每一个程序写好后都建议留下注释,方便他人或自己来看;
5.FB和FC的使用:可以根据控制要求或自己来选择。
本文将数据类型,表达式、定时器、边沿指令、转换指令、块结构、控制指令进行简单回顾和复习,然后一起编写了第一个面向对象的程序设计,好的,那么以上就是本篇文章的全部内容啦!另外,如有不足之处,可以在下面留言!