在S7300400型PLC中使用高级语言编程.docx
《在S7300400型PLC中使用高级语言编程.docx》由会员分享,可在线阅读,更多相关《在S7300400型PLC中使用高级语言编程.docx(21页珍藏版)》请在冰点文库上搜索。
在S7300400型PLC中使用高级语言编程
在S7300/400型PLC中使用高级语言编程
S7-SCL是一种类似于Pasical、Deliphi的高级编程语言,其符合国际标准IEC61131-3,也就是说支持该标准的任意厂家的PLC均可以使用与之相似的语言编程。
这种语言适合于处理复杂的逻辑和大量的数学运算,由于其具有高级语言的编程结构,因此和S7的STL语句表编程方式比较起来有着更加方便的控制方式,可以这样说,只要是必须使用语句表的地方,我们均可以考虑使用SCL,也许STL在执行时比SCL更加高效,但事实上也不一定,首先SCL可以编译成STL,同时SCL设计时可以优化编程,而STL若运用不当,可能还会将低效率。
当然在目前的这种系列的PLC上,效率对于我们来说已是次要的,我们更关心的是编程结构。
就像在PC机上,舍弃了汇编语言,而主要采用C/C++等高级语言。
总体来说,SCL适合于编写标准功能块,由于在维护中,它和STL一样,不象Lad一样利于维护,因此这些标准功能块都应该有文档说明,以便用户了解其功能。
下面的内容主要是参考西门子的S7-SCL文档,对SCL进行了系统的介绍,最后给出了示例。
这里假设读者是学过S7-300/400编程,并曾经学过至少一种计算机高级编程语言。
一、软件的使用
1、创建一个新的S7-SCLSource文件
打开工程项目à选择CPU站à选择S7Programà选择Sources
在右边窗口的空白处点右键选InsertNewObjectà点击SCLSource
双击创建的SCLSource文件,进入SCL编辑界面。
2、块保护
在SCLSource文件的开头添加关键字:
KNOW_HOW_PROTECT,当打开由其创建的块时,只能显示参数,而看不到内容。
3、主菜单”Insert”下的”BlockTemplate”可用于插入如OB,FB等各种块的结构。
”ControlStructure”菜单可插入各种流程控制结构,这些都可以简化编程。
4、在运行程序之前,首先必须对它进行编译,可以编译整个Source文件或者某个被选择的块,通过选择菜单File>CompileSelectedBlocks。
也可以把几个Source文件一起进行编译,其方法是创建一个S7-SCLcompilationcontrolfile.在该文件中依次输入需要编译的SCLSource文件名,然后执行编译即可。
二、语法规则
1、编写SCLSource文件的一般规则
●FB,FC,OB,DB以及用户定义的UDT,它们使用的任意数字号均可以在SCLSource中编辑。
●每种块类型都有它自己的结构。
●每段落或者每个变量的声明以符号”;”标志结束。
●不区分大小写。
●注释仅存在于程序文档中,它不影响程序运行。
●当一个功能块被调用时,其背景数据块被自动创建,因此它们不需要被编辑。
●DB0有特定用途,因此在程序中不能创建DB0.
2、编写块的先后次序
●被调用的块必须位于调用块之前。
●UDT的定义必须位于其被使用的位置之前。
●共享数据块必须位于那些使用它的所有块之前。
三、数据类型
1、数据类型预览
Ⅰ、基本数据类型
2、补充
<1>、DATE_AND_TIMEDataType
其值的范围:
DT#1990-01-01-0:
0:
0.0---------DT#2089-12-31-23:
59:
59.999
该类型以BCD码形式存储。
例如20/Oct./199512:
20:
30and10milliseconds显示如下:
DATE_AND_TIME#1995-10-20-12:
20:
30.10
DT#1995-10-20-12:
20:
30.10
<2>STRING
e.g.声明
VAR
Text1:
String[123];//该字符串的最大容量为123个字符
Text2:
String;//该字符串的默认容量为254个字符
END_VAR
初始化:
x:
STRING[7]:
='Address';//在使用STRING前,必须对它赋值。
FUNCTIONTest:
STRING[45]
VAR_TEMP
x:
STRING[45];
END_VAR
x:
='a';
x:
=concat(in1:
=x,in2:
=x);
Test:
=x;//返回值
END_FUNCTION
<3>数组类型
e.g.
VAR
CONTROLLER1:
//声明3行、4列的二位整数数组,并对其初始化
ARRAY[1..3,1..4]OFINT:
=-54,736,-83,77,
-1289,10362,385,2,
60,-37,-7,103;
CONTROLLER2:
ARRAY[1..10]OFREAL;//声明10个数的一维实数数组
END_VAR
注:
数组的最大维数为6维,数组的索引范围为-32768---32767之间的任意整数。
所有的基本数据类型均可用于数组。
数组可以使用变量进行索引,例如:
arrname_1[i]:
=arrname_2[j];
<4>STRUCT类型
e.g.声明一个结构MOTOR中包含另一个结构DATA。
对结构声明时,可以初始化元素,也可以在使用之前再初始化。
VAR
MOTOR:
STRUCT
DATA:
STRUCT
LOADCURR:
REAL;
VOLTAGE:
INT:
=5;
END_STRUCT;
END_STRUCT;
END_VAR
结构以WORD的形式结尾,否则系统自动把丢失的字节补到结构中去。
<5>用户定义类型UDT(使用关键字TYPE)
TYPE//定义名字为MEASVALUES的数据类型
MEASVALUES:
STRUCT
BIPOL_1:
INT:
=5;
BIPOL_2:
WORD:
=W#16#FFAA;
BIPOL_3:
BYTE:
=B#16#F1;
BIPOL_4:
WORD:
=W#16#1919;
MEASURE:
STRUCT
BIPOLAR_10V:
REAL;
UNIPOLAR_4_20MA:
REAL;
END_STRUCT;
END_STRUCT;
END_TYPE
//在FB10中使用该类型
FUNCTION_BLOCKFB10
VAR
MEAS_RANGE:
MEASVALUES;//创建UDT数据
END_VAR
BEGIN
//使用UDT数据
MEAS_RANGE.BIPOL_1:
=-4;
MEAS_RANGE.MEASURE.UNIPOLAR_4_20MA:
=2.7;
END_FUNCTION_BLOCK
<6>POINTER类型
e.g.
//定义功能块FC100
FUNCTIONFC100:
VOID//VOID表明该功能不返回值
VAR_IN_OUT//定义FC100的输入输出型参数
N_out:
INT;
out:
POINTER;//定义POINTER型数据类型,参数均为临时变量
END_VAR
VAR_TEMP//定义临时变量
ret:
INT;
END_VAR
BEGIN//进入函数主体
//...
ret:
=SFC79(N:
=N_out,SA:
=out);
END_FUNCTION
//定义功能块FB100
FUNCTION_BLOCKFB100
VAR//定义静态变量,即离开块后仍旧保存状态的变量
ii:
INT;
aa:
ARRAY[1..1000]OFREAL;
END_VAR
BEGIN
//...
FC100(N_out:
=ii,out:
=aa);//调用FC100,使用指针的方式传递整个数组
//...
END_FUNCTION_BLOCK
<7>ANY类型
e.g.
VAR_INPUT//输入型变量
iANY:
ANY;//定义为ANY
END_VAR
VAR_TEMP
pANY:
ANY;//定义为ANY
END_VAR
CASEiiOF//CASE分支语句
1:
pANY:
=MW4;//将MW4的地址赋给pANY
//ofMW4
3..5:
//等于3,4,5的情况下
pANY:
=aINT[ii];//pANYcontainstheaddress
//oftheiith
//elementoftheaINTfield;
100:
pANY:
=iANY;//pANYcontainsthevalue
//oftheiANYinputvariable
ELSE
pANY:
=NIL;//pANYcontainsthevalue
//oftheNILpointer
END_CASE;
SFCxxx(IN:
=pANY);
四、局部变量和参数的声明
1、变量
静态变量:
用于保持块的数据,该数据存在背景数据块中。
临时变量:
仅在块运行过程中存在。
若多个变量的数据类型一致,可用如下方式:
VALUE2,VALUE3,VALUE4,....:
INT;
声明时可以初始化:
VALUE:
REAL:
=20.25;
数组的初始化有两种方式:
CONTROLLER1:
ARRAY[1..2,1..2]OFINT:
=-54,736,-83,77;
当把相邻的数组元素赋相同的值时,例如,把A3[2]到A3[11]的值设为100.0:
A3:
ARRAY[1..12]OFREAL:
=0.0,10(100.0),1.0;
2、块参数
输入参数:
用于接收当块被调用时的输入值,他们是只读的。
输出参数:
传输当前值到这个调用块,在被调用块中应该对该参数赋值
输入/输出参数:
用于接收当块被调用时的输入值,并可以把结果返回到调用块。
3、使用多重背景
声明方式如下:
Supply1:
FB10;//Supply1为FB10的背景DB
Supply2,Supply3,Supply4:
FB100;//为FB100声明多个背景DB
Motor1:
Motor;//Motor为某个FB的符号名
4、变量的声明
五、常量
S7-SCL常量分位常量、数字常量、字符常量、时间常量,使用CONST…END_CONST声明。
e.g.
CONST
Number:
=10;//整数常量
TIMEOFDAY1:
=TIME#1D_1H_10M_22S_2MS;//时间常量
NAME:
='SIEMENS';//字符串常量
NUMBER2:
=2*5+10*4;
NUMBER3:
=3+NUMBER2;
END_CONST
1、位常量
Bool#false位的值为TRUE或者FALSE
8#1777778进制
DW#16#0000_000016进制
2、整数常量,它有多种表达方式
1510进制值为15
2#11112进制值为15
16#F16进制值为15
Value_2:
=2#0101;//2进制值为5
Value_3:
=8#17;//10进制值为14
Value_4:
=16#F;//16进制值为15
Value_5:
=INT#16#3f_ff//16进制值,类型被定义
3、Real常量
NUM4:
=-3.4;
NUM5:
=4e2;
NUM6:
=real#1.5;
4、字符常量(单个字符)
Charac_1:
='B';
Charac_2:
=char#43;
Charac_3:
=char#'B';//字符’B’
CHARACTER:
='$41';//字符'A'
5、字符串常量
NAME:
='SIEMENS';
6、日期常量
TIMEVARIABLE1:
=DATE#1995-11-11;
TIMEVARIABLE2:
=D#1995-05-05;
7、时间常量
Interval1:
=TIME#10.5S;
Interval2:
=T#3D_2S_3MS;
8、Time-of-Day常量
TIMEOFDAY1:
=TIME_OF_DAY#12:
12:
12.2;
TIMEOFDAY2:
=TOD#11:
11:
11;
9、DateandTime常量
TIMEOFDAY1:
=DATE_AND_TIME#1995-01-01-12:
12:
12.2;
TIMEOFDAY2:
=DT#1995-02-02-11:
11:
11;
六、CPU的内存区域
1、可以直接操作字节、字、位
STATUSBYTE:
=IB10;
STATUS_3:
=I1.1;
MEASVAL:
=IW20;
2、可以通过索引对位、字、字节操作,该索引可以是变量
MEASVAL_1:
=IW[COUNTER];//若COUNTER=5,则MEASVAL_1的值为IW5
OUTLABEL:
=I[BYTENO,BITNO];//若BYTENO=3,BITNO=1,则OUTLABEL=I3.1
注:
当获取的数据类型是BYTE,WORDorDWORD,时,使用一个索引参数,当获取的数据类型为BOOL时,必须使用两个索引参数,分别指定字节号和位号。
3、对数据块的操作
STATUSBYTE:
=DB101.DB10;//字节操作
STATUS_2:
=DB12.DX[WNO,BITNO];//位操作,支持索引
STATUSBYTE:
=Status_data.DW[COUNTER];//字操作,支持索引
MEASVAL:
=Measdata.DW20;
STATUS_1:
=WORD_TO_BLOCK_DB(INDEX).DW10;
注:
和Lad及STL语言比较起来,SCL在对数据块中的字、字节等操作时,少一个”B”字符。
七、表达式、操作符和地址
1、操作符预览
八、控制流程
1、IF选择语句
IFconditionTHEN
…
ELSIFconditionTHEN//ELSIF语句可以不使用,或者使用一个或者多个
…
ELSE//ELSE语句可以不使用
…
END_IF;
e.g.
IFARRAY[INDEX]=INDEXTHEN
CONTINUE;
END_IF;
2、CASE选择语句
CASEintVariantOF
1:
DISPLAY:
=OVEN_TEMP;
2:
DISPLAY:
=MOTOR_SPEED;
3..10:
DISPLAY:
=INT_TO_DINT(TW);//可以指定连续的值
QW4:
=16#0004;
11,13,19:
DISPLAY:
=99;//也可以把一系列值列出来
QW4:
=16#0005;
ELSE:
//ELSE:
可以省略
DISPLAY:
=0;
TW_ERROR:
=1;
END_CASE;
3、FOR循环语句
FUNCTION_BLOCKFOR_EXA
VAR
INDEX:
INT;
IDWORD:
ARRAY[1..50]OFSTRING;
END_VAR
BEGIN
FORINDEX:
=1TO50BY2DO//从1到50,增量为2
IFIDWORD[INDEX]='KEY'THEN
EXIT;//退出循环
END_IF;
END_FOR;
END_FUNCTION_BLOCK
注:
一些关键字
EXIT退出其所在的循环。
CONTINUE终止当前循环的执行,控制程序进入下一循环。
RETURN退出当前正在被执行的块。
4、WHILE循环
WHILEINDEX<=50ANDIDWORD[INDEX]<>'KEY'DO//两个条件均满足才执行循环
INDEX:
=INDEX+2;
END_WHILE;
5、REPEAT循环
REPEAT
INDEX:
=INDEX+2;//该语句与WHILE的区别是UNTIL之前的语句总是先执行一次
UNTILINDEX>50ORIDWORD[INDEX]='KEY'//这两条件之一若满足,则退出循环
END_REPEAT;
6、GOTO跳转语句
IFA>BTHEN
GOTOLAB1;//若条件满足,则跳到LAB1处
ELSIFA>CTHEN
GOTOLAB2;
END_IF;
//...
LAB1:
INDEX:
=1;
GOTOLAB3;
LAB2:
INDEX:
=2;
…
7、调用块
绝对地址调用,例如:
FB10.DB20(X1:
=5,X2:
=78,......);//参数可以任意排列
FC31(X1:
=5,Q1:
=Checksum);
符号地址调用,例如:
DRIVE.ON(X1:
=5,X2:
=78,......);
DISTANCE(X1:
=5,Q1=:
Checksum);
每一个功能块有一个输入隐藏参数EN,和一个输出隐藏参数ENO,这两个参数是系统设定的,均为BOOL型,不需要声明,但在编程中可以使用,例如:
//若MY_ENABLE为FALSE,则FC85不会被执行,只有为TRUE,才会执行
Result:
=FC85(EN:
=MY_ENABLE,PAR_1:
=27);
FB30.DB30([Parametersupply]);
IFENOTHEN//若FB30的调用没有问题,则…
//...
ELSE
//...
END_IF;
九、定时器和计数器
1、计数器
S_CU增计数器
S_CD减计数器
S_CUD增/减计数器
e.g.
S_CUD(C_N=C12,//绝对调用定时器,指定计数器号
CD:
=I0.0,
CU:
=I0.1,
S:
=I0.2&I0.3,//置位条件
PV:
=120,//设定计数器值
R:
=FALSE,//复位条件
CV:
=binVal,//输出参数,二进制计数值
Q:
=actFlag);//输出参数,计数器的状态
FUNCTION_BLOCKCOUNT
VAR_INPUT
Count:
ARRAY[1..4]ofSTRUCT
C_NINT;
PV:
WORD;
END_STRUCT;
…
END_VAR
…
FORI:
=1TO4DO//动态调用计数器
S_CD(C_N=Count[I].C_NO,S:
=true,PV:
=Count[I].PV);
END_FOR;
FUNCTION_BLOCKCOUNTER
VAR_INPUT
MYCounter:
COUNTER;
END_VAR
…
CurrVal:
=S_CD(C_N=MyCounter,.....);//动态调用计数器
2、定时器
定时器有5种,依次为:
S_PULSES_PEXTS_ODTS_ODTSS_OFFDT
VAR
CurrTime:
S5time;
BiVal:
word;
ActFlag:
bool;
END_VAR
//在调用定时器时,部分参数可以省略,但左边的赋值变量一定不能省略。
CurrTime:
=S_ODT(T_N=T10,//绝对调用,制定定时器号
S:
=TRUE,//置位条件
TV:
=T#1s,//设定定时器值
R:
=FALSE,//复位条件
BI:
=biVal,
Q:
=actFlag);
FUNCTION_BLOCKTIME
VAR_INPUT
MY_TIMER:
ARRAY[1..4]ofSTRUCT
T_NINT;
TV:
WORD;
END_STRUCT;
…
END_VAR
…
FORI:
=1TO4DO
CurrTime:
=S_ODT(T_N=MY_TIMER[I].T_NO,S:
=true,
MY_TIMER[I].TV);
END_FOR;
FUNCTION_BLOCKTIMER
VAR_INPUT
mytimer:
TIMER;
END_VAR
…
CurrTime:
=S_ODT(T_N=mytimer,.....);
十、S7-SCL中的标准功能
1、数据类型转换函数
隐式转换,其依照的顺序为:
BOOL>BYTE>WORD>DWORD
INT>DINT>REAL
e.g.
VAR
PID_CTRLLER_1:
BYTE;
PID_CTRLLER_2:
WORD;
END_VAR
IF(PID_CTRLLER_1<>PID_CTRLLER_2)THEN...//此时PID_CTRLLER_1被转换成WORD
当然,也可以使用以下功能显示的转换:
BOOL_TO_BYTE、BOOL_TO_DWORD、BOOL_TO_WORD、BYTE_TO_DWORD、BYTE_TO_WORD、CHAR_TO_STRING、DINT_TO_REAL、INT_TO_DINT、INT_TO_REAL、WORD_TO_DWORD
BYTE_TO_BOOL:
Copiestheleastsignificantbit
DINT_TO_TOD:
CopiesthebitstringY
DINT_TO_BOOL:
DWORD_TO_BOOL(DINT_TO_DWORD(x))Y
DINT_TO_BYTE:
DWORD_TO_BYTE(DINT_TO_DWORD(x))Y
DINT_TO_STRING:
DI_STRNGY
DINT_TO_BCD(x)
DINT_TO_BCD_DWORD(x)
…
2、ROUND和TRUNC
ROUND():
将REAL数四舍五入取整返回DINT
TRUNC():
舍弃REAL数的小数部分取整返回DINT
3、一般数学函数
例子:
RESULT:
=ABS(-5);//5
RESULT:
=SQRT(81.0);//9
RESULT:
=SQR(23);//529
RESULT:
=EXP(4.1);//60.340...
RESULT:
=EXPD(3);//1_000
PI:
=3.141592;
RESULT:
=SIN(PI/6);//0.5
6、移位函数
ROL、ROR、SHL、SHR
例子:
RESULT:
=ROL(IN:
=BYTE#2#1101_0011,N:
=5);//2#011