//************************ //****得到代码执行周期******* //************************ 1、OB1的临时变量区提供了OB1_PREV_CYCLE INT 上一次扫描的运行时间(ms),,长时间的累积会有不少的误差。为什么呢,因为系统提供给你的数值可能是有舍弃小数后值。而且提供的是用户程序运行时间,是否包含接口扫描、通讯、映射等时间不得而知。你可以通过累积OB1_PREV_CYCLE 和sfc64的后台时间比较就知道,两个的差别。 我的方法是通过读取系统时钟,这样无累积误差,(SFC64提供正向增长的双字运行时间) //****获得系统时钟和程序执行周期*** CALL SFC 64 ( RET_VAL := LD 96); L LD 96; L #sysT; -D ; JPZ posA; //计数满了,就少计一个周期,影响可以忽略 L #cycT; posA: T #cycT; L LD 96; T #sysT; //------------------- 消除了系统提供时钟的累积误差。误差最大一个执行周期(3~10ms); //*************************** //*******多功能定时器******** //*************************** 嵌入程序的定时器,是实现功能块封装的重要部分,实现方便的移植 系统提供的IEC定时器,复位比较麻烦,必须再次执行; 自制FB功能块可同时方便实现以下几个功能 1、开关量滤波功能;延时接通延时断开,也可处理有干扰波动值阀值比较; 2、Ton定时器;(TofSet=0) 3、Tof定时器;(TonSet=0) 定时精度最小1ms,实际精度是一个周期; 定时范围2,147,483,647ms(596小时); //--以下是写的FB块,测试用了好长时间,也还能精简,抛砖引玉;欢迎指教; //---- //符号注释:开关量滤波,单位ms; //计数到后, tonAct(DINT)/tofAct(DINT)不再递增。设定值小于等于0,输出同步输入。 //设定时间=set*ration,单位ms。电平使能,复位结束后,使能还在则重新计时; VAR_INPUT TonSet : INT ; //设定延时启动值,默认为0无延时;DIW0 TofSet : INT ; //设定延时断开值,默认为0无延时;DIW2 Ratio : INT := 100; //设定值倍率1=1ms(默认100ms)DIW4 CycT : INT ; //OB1上次扫描周期,单位ms,DIW6 Rst : BOOL ; //复位计时器内部保存值和输出,DIX8.0 En : BOOL ; //需要滤波的DI,DIX8.1 END_VAR VAR_OUTPUT OK : BOOL ; //滤波输出,DIX10.0 END_VAR VAR tonAct : DINT ; //DID12 tofAct : DINT ; //DID16 END_VAR //************************************* BEGIN SET ; L l#0; A #Rst; JCN ton; R #OK; T #tonAct; T #tofAct; BE ; ton: A #En; JCN tof; T #tofAct; A #OK; BEc ; L #Ratio; L #TonSet; *I ; //不要用*D,如果设定错误成负数,会错误被解释成正的大值; L #tonAct; <=D ; S #OK; BEC ; L #CycT; +D ; T #tonAct; BE ; tof: T #tonAct; AN #OK; BEc ; L #Ratio; L #TofSet; *i ; //不要用*D,如果设定错误成负数,会错误被解释成正的大值; L #tofAct; <=D ; R #OK; BEC ; L #CycT; +D ; T #tofAct; BE ; END_FUNCTION_BLOCK |
电工学习网 ( )
GMT+8, 2023-4-17 15:05