回复:SCL语言实现的FIFO队列功能块(基于循环数组)

大鹏、

  • 帖子

    3
  • 精华

    0
  • 被关注

    2

论坛等级:游民

注册时间:2016-06-28

普通 普通 如何晋级?

发布于 2017-07-03 12:15:06

3楼

FUNCTION_BLOCK "LoopQueue"

{ S7_Optimized_Access := 'TRUE' }

VERSION : 0.1

   VAR_INPUT 

      capacity : Int := 10;

      i_pop : Bool;

      i_push : Bool;

      i_push_data : "TEST_DATA_STRUCT";

      i_clear : Bool;

      i_err_reset : Bool;

   END_VAR


   VAR_OUTPUT 

      o_isEmpty : Bool;

      o_size : Int;

      o_front : "TEST_DATA_STRUCT";

      o_error : Bool;

      o_status : Int;

   END_VAR


   VAR RETAIN

      "begin" : Int := 0;

      end : Int := 0;

      data_init : "TEST_DATA_STRUCT";

      queue : Array[0..99] of "TEST_DATA_STRUCT";

   END_VAR

   VAR 

      R_TRIG_Push {OriginalPartName := 'R_TRIG_1500'; LibVersion := '1.0'} : R_TRIG;

      R_TRIG_Pop {OriginalPartName := 'R_TRIG_1500'; LibVersion := '1.0'} : R_TRIG;

      R_TRIG_Clear {OriginalPartName := 'R_TRIG_1500'; LibVersion := '1.0'} : R_TRIG;

      R_TRIG_Reset {OriginalPartName := 'R_TRIG_1500'; LibVersion := '1.0'} : R_TRIG;

   END_VAR


   VAR_TEMP 

      i : Int;

   END_VAR



BEGIN

IF #capacity = 0 THEN //capacity不能为0!防止用户输入为0导致CPU除0故障!

   #o_error := TRUE;

   #o_status := 16#4000;

ELSE

   

(*** PUSH ***)

   #R_TRIG_Push(CLK := #i_push);

   IF #R_TRIG_Push.Q THEN

       IF (((#end + 1) - ((#end + 1) / #capacity) * #capacity)) = #begin THEN  //判断队列是否满了,end+1取模

           #o_error := TRUE;

           #o_status := 16#4001; //错误码:队满

       ELSE

           #queue[#end] := #i_push_data; //入队

           #end := (#end + 1) - ((#end + 1) / #capacity) * #capacity; //队尾+1

       END_IF;

   END_IF;

   

(*** POP ***)

   #R_TRIG_Pop(CLK := #i_pop);

   IF #R_TRIG_Pop.Q THEN

       IF #end = #begin THEN //判断队空

           #o_error := TRUE;

           #o_status := 16#4002;

       ELSE

           #queue[#begin] := #data_init; //队首数据清零

           #begin := (#begin + 1) - ((#begin + 1) / #capacity) * #capacity;  //队首前移,begin+1取模

       END_IF;

   END_IF;

   

(*** FRONT(队首元素) ***)

   IF #end = #begin THEN

       #o_front := #data_init;  //队列为空则返回全零数据,因为FB块Output变量总是会输出值

   ELSE

       #o_front := #queue[#begin];

   END_IF;

   

(*** SIZE ***)

//#o_size := (#end - #begin + #capacity) % #capacity; //SCL貌似没有%取模运算,只能自己转换了

#o_size := (#end - #begin + #capacity) - ((#end - #begin + #capacity) / #capacity) * #capacity;

(*** isEmpty ***) //判否,放最后,防止变化后本CPU周期内判断错误

IF #begin = #end THEN

   #o_isEmpty := TRUE;

ELSE

   #o_isEmpty := FALSE;

END_IF;

(*** CLEAR(清空队列) ***)

#R_TRIG_Clear(CLK := #i_clear);

IF #R_TRIG_Clear.Q THEN

   FOR #i := 0 TO #capacity - 1 DO

       #queue[#i] := #data_init;

   END_FOR;

END_IF;

(*** ERROR RESET ***)

#R_TRIG_Reset(CLK := #i_err_reset);

IF #R_TRIG_Reset.Q THEN

   #o_error := FALSE;

   #o_status := 0;

END_IF;

END_IF;

END_FUNCTION_BLOCK


还有诗和远方
评论
编辑推荐: 关闭

请填写推广理由:

本版热门话题

SIMATIC S7-1500系列

共有10592条技术帖

相关推荐

热门标签

相关帖子推荐

guzhang

恭喜,你发布的帖子

评为精华帖!

快扫描右侧二维码晒一晒吧!

再发帖或跟帖交流2条,就能晋升VIP啦!开启更多专属权限!

  • 分享

  • 只看
    楼主

top
您收到0封站内信:
×
×
信息提示
很抱歉!您所访问的页面不存在,或网址发生了变化,请稍后再试。