得到准确ms级的代码执行周期,做自己的多功能定时器块

//************************

//****得到代码执行周期*******

//************************

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

得到准确ms级的代码执行周期,做自己的多功能定时器块

相关文章:

你感兴趣的文章:

标签云: