八、控制流程 1、IF选择语句 IF condition THEN … ELSIF condition THEN // ELSIF语句可以不使用,或者使用一个或者多个 … ELSE // ELSE语句可以不使用 … END_IF ; e.g. IF ARRAY[INDEX] = INDEX THEN CONTINUE ; END_IF ;
2、CASE选择语句 CASE intVariant OF 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_BLOCK FOR_EXA VAR INDEX: INT ; IDWORD: ARRAY [1..50] OF STRING; END_VAR BEGIN FOR INDEX := 1 TO 50 BY 2 DO //从1到50,增量为2 IF IDWORD [INDEX] = \'KEY\' THEN EXIT; //退出循环 END_IF; END_FOR; END_FUNCTION_BLOCK 注:一些关键字 EXIT 退出其所在的循环。 CONTINUE 终止当前循环的执行,控制程序进入下一循环。 RETURN 退出当前正在被执行的块。 4、WHILE循环 WHILE INDEX <= 50 AND IDWORD[INDEX] <> \'KEY\' DO //两个条件均满足才执行循环 INDEX := INDEX + 2; END_WHILE ;
5、REPEAT循环 REPEAT INDEX := INDEX + 2 ; //该语句与WHILE的区别是UNTIL之前的语句总是先执行一次 UNTIL INDEX > 50 OR IDWORD[INDEX] = \'KEY\' //这两条件之一若满足,则退出循环 END_REPEAT ;
6、GOTO跳转语句 IF A > B THEN GOTO LAB1 ; //若条件满足,则跳到LAB1处 ELSIF A > C THEN GOTO LAB2 ; END_IF ; // . . . LAB1: INDEX := 1 ; GOTO LAB3 ; 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 ([Parameter supply]); IF ENO THEN //若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_BLOCK COUNT VAR_INPUT Count: ARRAY [1..4] of STRUCT C_N INT; PV : WORD; END_STRUCT; … END_VAR … FOR I:= 1 TO 4 DO //动态调用计数器 S_CD(C_N=Count[I].C_NO, S:=true, PV:= Count[I].PV); END_FOR; FUNCTION_BLOCK COUNTER VAR_INPUT MYCounter:COUNTER; END_VAR … CurrVal:=S_CD(C_N=MyCounter,.....); //动态调用计数器
2、定时器 定时器有5种,依次为:S_PULSE S_PEXT S_ODT S_ODTS S_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_BLOCK TIME VAR_INPUT MY_TIMER: ARRAY [1..4] of STRUCT T_N INT; TV : WORD; END_STRUCT; … END_VAR … FOR I:= 1 TO 4 DO CurrTime:= S_ODT(T_N=MY_TIMER[I].T_NO, S:=true, MY_TIMER[I].TV); END_FOR;
FUNCTION_BLOCK TIMER 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 :Copies the least significant bit DINT_TO_TOD :Copies the bit string Y 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_STRNG Y DINT_TO_BCD(x) DINT_TO_BCD_DWORD(x) … 2、ROUND和TRUNC ROUND():将REAL数四舍五入取整返回DINT TRUNC():舍弃REAL数的小数部分取整返回DINT
3、一般数学函数 [upload=jpg]UploadFile/2006-8/200681018191678399.jpg[/upload] 例子: 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. 141 592 ; RESULT := SIN (PI / 6) ; //0.5 6、移位函数 ROL、ROR、SHL、SHR 例子: RESULT := ROL (IN:=BYTE#2#1101_0011, N:=5); //2#0111_1010 ,左移5位 ,移出的填充到右边空位 RESULT := ROR (IN:=BYTE#2#1101_0011, N:=2); //2#1111_0100 ,右移2位 ,移出的填充到左边空位 RESULT := SHL (IN:=BYTE#2#1101_0011, N:=3); //2#1001_1000 ,左移3位,空余部分用0填充 RESULT := SHR (IN:=BYTE#2#1101_0011, N:=2); //2#0011_0100 ,右移2位,空余部分用0填充
7、字符串函数 由于PLC编程中字符、字符串的使用比较少,这里不详叙,感兴趣的可以参考西门子文档中的 14.4 Functions for Processing Strings (P293-P303)
8、 选值函数 <1>最大值函数 //用于获取这些参数中的最大值,参数最多可以有32个,其参数类型除了S5TIME以外,任意其他数//子类型均可以,但所有的参数数据类型必须一致。 A:=MAX(IN1:=a, IN2:=b, IN3:=c, IN4:=d...); <2>最小值函数 //用于获取这些参数中的最小值,参数最多可以有32个,其参数类型除了S5TIME以外,任意其他数//子类型均可以,但所有的参数数据类型必须一致。 A:=MIN(IN1:=a, IN1:=b, IN1:=c, IN1:=d); <3>极限值函数 A:=LIMIT(MN:=5, IN:= Execution steps, MX:= 10); <4>MUX函数 A:=MUX(K:=SELECT, IN0:= Steps, IN1:=Number, IN2:=Total); 9、系统功能/功能块、标准库 SCL像其他语言一样,可以调用各种功能块,包括系统功能、功能块SFC/SFB
十一、示例 (均在PLC-SIM上测试通过) 1、编写位偏移程序 传递M变量的起始字节和位、偏移量,然后根据偏移量,算出当前M变量的字节和地址。例如针对M5.4,若给定偏移量1,则当前还是M5.4,若给定2,则为M5.5,依次类推,若给定偏移量6,则为M6.1 //根据偏移量来设定字节和位 FUNCTION FC200: void VAR_INPUT //输入变量 byteNo:INT; //指定M起始字节号 bitNo:INT; //指定起始位号 bitNum:INT; //指定位数 END_VAR VAR_OUTPUT //输出变量 currBit:INT; //当前位 currByte:INT; //当前字节 END_VAR VAR_TEMP tmp:INT; END_VAR BEGIN tmp:=(bitNo+bitNum-1)DIV 8; currByte:=byteNo+tmp; currBit:=bitNo+bitNum-(8*tmp+1); END_FUNCTION
2、功能选择程序
假设某个机床有若干过手动功能,使用两个按钮”+”和”-“,按一次”+”,功能号加一,然后相应的功能选择指示灯被点亮,譬如,当前功能3被选中,与之对应的指示灯亮,这时按一次按钮”+”,则功能4被选中,与之对应的指示灯亮,而与功能3对应的指示灯灭,同时,当功能号到达最大值时,若再按一次按钮”+”,则功能号转到1,重新开始循环,按钮”-“与”+”正好相反,用于控制功能号递减。同时要求,当按住某个按钮超过1s时,则功能号每过200ms钟加一或者减一。 /////////////////////////////////////////////主要控制功能FC10//////////////////////////////////////// FUNCTION FC10: VOID VAR_INPUT //输入变量 fnAdd:BOOL; //接收\"+\"按钮 fnSub:BOOL; //接收\"-\"按钮 byteNo:INT; //指定M起始字节号,这些M位与相应得某个功能对应。 bitNo:INT; //指定起始位号 bitNum:INT; //指定总的位数 END_VAR VAR //静态变量 pus1:BOOL; //记录按钮\"+\"的脉冲 pus2:BOOL; //记录按钮\"-\"的脉冲 button:BOOL; //确定按钮\"+\"或者按钮\"-\"被按下 currNo:INT; //记录当前的功能号 currBit:INT; //当前位 currByte:INT; //当前字节 //定时器输出 p1:BOOL; p2:BOOL; p11:BOOL; //记录按钮\"+\"的时钟 p111:BOOL; p22:BOOL; //记录按钮\"-\"的时钟 p222:BOOL; CurrTime:S5TIME; END_VAR VAR_TEMP i:INT; END_VAR BEGIN ////若都接通,则推出块 IF fnAdd&fnSub THEN RETURN; END_IF; /////////////////////////////////////////获取按钮\"+\"的脉冲/////////////////////////////////////////// IF fnAdd &(button=false) THEN pus1:=true; ELSE pus1:=false; END_IF; //////////////////////////////////////////按钮\"-\"的脉冲///////////////////////////////// IF fnSub &(button=false) THEN pus2:=true; ELSE pus2:=false; END_IF; IF (fnSub&(fnAdd=false))OR (fnAdd&(fnSub=false)) THEN button:=true; ELSE button:=false; END_IF; //////////////////////////添加定时器监测//////////////////////////////////////////////////// CurrTime:=S_ODT(T_NO:=T10, S:=fnAdd, TV:=T#800ms,Q:=p1); //按钮按下的时间 CurrTime:=S_ODT(T_NO:=T11, S:=p1&p111, TV:=T#200ms,Q:=p11); IF p11=true THEN p111:=false; //当定时器有输出后,断开信号,使其在下一扫瞄周期中无输出 ELSE p111:=true; //在按钮按下的情况下重启定时器计时 END_IF; CurrTime:=S_ODT(T_NO:=T20, S:=fnSub, TV:=T#1s,Q:=p2); CurrTime:=S_ODT(T_NO:=T21, S:=fnSub&p222, TV:=T#200ms,Q:=p22); IF p22=true THEN p222:=false; //当定时器有输出后,断开信号,使其在下一扫瞄周期中无输出 ELSE p222:=true; //在按钮按下的情况下重启定时器计时 END_IF; /////////////////////////////////////////////////////////////////////////////////////////////////////// //功能号从1开始,最后一个的号等于bitNum IF pus1=true OR p11 THEN //按钮\"+\"的脉冲 IF currNo currNo:=currNo+1; ELSE currNo:=1; END_IF; ELSIF pus2=true OR p22 THEN // 按钮\"-\"的脉冲 IF currNo>1 THEN currNo:=currNo-1; ELSE currNo:=bitNum; END_IF; END_IF; //把它的上一个功能置0 m[currByte,currBit]:=false; fc200(byteNo:=byteNo,bitNo:=bitNo,bitNum:=currNo,currBit:=currBit, currByte:=currByte); //把当前功能置1 m[currByte,currBit]:=true; END_FUNCTION 注:上程序有些繁琐,主要是在编写按钮脉冲时有些费事,好像SCL不提供脉冲沿检测函数。 作者单位:东风康明斯股份有限公司 地址:襄樊.东风康明斯公司、曲凸事业部 441004 Email:wuyang26@sohu.com
[此贴子已经被作者于2006-8-10 18:19:39编辑过] |