恭喜,你发布的帖子
发布于 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
请填写推广理由:
分享
只看
楼主