变量声明
Input
push Bool false 非保持 True True True False 入队
pop Bool false 非保持 True True True False 出队
reset Bool false 非保持 True True True False 复位
itemIndex UDInt 0 非保持 False False False False 入队/出队元素起始索引号
itemLen UDInt 0 非保持 True True True False 入队/出队元素长度
Output
queueUsed DInt 0 非保持 True True True False
queueUnused DInt 0 非保持 True True True False
error Bool false 非保持 True True True False 故障状态
status Word 16#0 非保持 True True True False 状态代码
InOut
item Array[*] of Byte False False False False 入队或出队的元素
queue Array[*] of Byte False False False False 队列空间
Static
statHeadIndex DInt 0 非保持 True True True False
statTailIndex DInt 0 非保持 True True True False
statQueueUsed DInt 0 非保持 True True True False
statQueueUnused DInt 0 非保持 True True True False
statItemIndex DInt 0 非保持 False False False False 入队/出队元素起始索引号
statReturn Bool false 非保持 True True True False
Temp
tempInterErr Int
tempQueueLowBnd DInt
tempQueueUpBnd DInt
tempQueueSize DInt
tempCount UDInt
tempItemSize DInt
tempItemCount UDInt
retVal Int
tempItemUpBnd DInt
tempItemLowBnd DInt
Constant
BUFFER_FULL Word 16#8a04 队列剩余空间不足
BUFFER_EMPTY Word 16#8a05 队列剩余元素不足
ITEM_LENGTH_ZERO Word 16#8a06 数据项长度为0
ITEM_INDEX_LIMIT Word 16#8a07 数据项索引号超边界
ITEM_LENGTH_LIMIT Word 16#8a08 数据项长度超限
NO_ERROR Word 16#0000
程序
//队列边界及容量
REGION ItemIndex
#tempItemLowBnd := LOWER_BOUND(ARR := #item, DIM := 1);
#tempItemUpBnd := UPPER_BOUND(ARR := #item, DIM := 1);
#statItemIndex := UDINT_TO_DINT(#itemIndex);
END_REGION
REGION QueueSize
#tempQueueLowBnd := LOWER_BOUND(ARR := #queue, DIM := 1);
#tempQueueUpBnd := UPPER_BOUND(ARR := #queue, DIM := 1);
#tempQueueSize := #tempQueueUpBnd - #tempQueueLowBnd + 1;
END_REGION
//入队
REGION Push
IF #push = TRUE THEN
IF #itemLen = 0 THEN
#error := TRUE;
#status := #ITEM_LENGTH_ZERO;
RETURN;
END_IF;
IF #statItemIndex < #tempItemLowBnd OR #statItemIndex > #tempItemUpBnd THEN
#error := TRUE;
#status := #ITEM_INDEX_LIMIT;
RETURN;
END_IF;
IF UDINT_TO_DINT(#itemIndex + #itemLen) > #tempItemUpBnd + 1 THEN
#error := TRUE;
#status := #ITEM_LENGTH_LIMIT;
RETURN;
END_IF;
IF #itemLen > #statQueueUnused THEN
#error := TRUE;
#status := #BUFFER_FULL;
RETURN;
END_IF;
IF #itemLen>#tempItemSize-#statTailIndex+1 THEN
#retVal := MOVE_BLK_VARIANT(SRC := #item,
COUNT := #itemLen,
SRC_INDEX := UDINT_TO_DINT(#itemIndex) - #tempItemLowBnd,
DEST_INDEX := #statTailIndex-#tempItemLowBnd,
DEST => #queue);
ELSE
#retVal := MOVE_BLK_VARIANT(SRC := #item,
COUNT := DINT_TO_UDINT(#tempItemSize - #statTailIndex + 1),
SRC_INDEX := UDINT_TO_DINT(#itemIndex) - #tempItemLowBnd,
DEST_INDEX := #statTailIndex-#tempItemLowBnd,
DEST => #queue);
#retVal := MOVE_BLK_VARIANT(SRC := #item,
COUNT := #itemLen - DINT_TO_UDINT(#tempItemSize - #statTailIndex + 1),
SRC_INDEX := UDINT_TO_DINT(#itemIndex) - #tempItemLowBnd + #tempItemSize - #statTailIndex + 1,
DEST_INDEX := 0,
DEST => #queue);
END_IF;
#statTailIndex += UDINT_TO_DINT(#itemLen);
IF #statTailIndex >= #tempQueueSize THEN
#statTailIndex := #statTailIndex - #tempQueueSize;
#statReturn := TRUE;
END_IF;
END_IF;
END_REGION
//出队
REGION Pop
IF #pop = TRUE THEN
IF #itemLen = 0 THEN
#error := TRUE;
#status := #ITEM_LENGTH_ZERO;
RETURN;
END_IF;
IF #statItemIndex < #tempItemLowBnd OR #statItemIndex > #tempItemUpBnd THEN
#error := TRUE;
#status := #ITEM_INDEX_LIMIT;
RETURN;
END_IF;
IF UDINT_TO_DINT(#itemIndex + #itemLen) > #tempItemUpBnd + 1 THEN
#error := TRUE;
#status := #ITEM_LENGTH_LIMIT;
RETURN;
END_IF;
IF #itemLen > #statQueueUsed THEN
#error := TRUE;
#status := #BUFFER_EMPTY;
RETURN;
END_IF;
IF #itemLen>#tempItemSize-#statHeadIndex THEN
#retVal := MOVE_BLK_VARIANT(SRC := #queue,
COUNT := DINT_TO_UDINT(#tempItemSize - #statHeadIndex),
SRC_INDEX := #statHeadIndex - #tempQueueLowBnd,
DEST_INDEX := UDINT_TO_DINT(#itemIndex) - #tempItemLowBnd,
DEST => #item);
#retVal := MOVE_BLK_VARIANT(SRC := #queue,
COUNT := #itemLen - DINT_TO_UDINT(#tempItemSize - #statHeadIndex + 1),
SRC_INDEX := 0,
DEST_INDEX := UDINT_TO_DINT(#itemIndex) - #tempItemLowBnd+(#tempItemSize - #statHeadIndex + 1),
DEST => #item);
ELSE
#retVal := MOVE_BLK_VARIANT(SRC := #queue,
COUNT := #itemLen,
SRC_INDEX := #statHeadIndex - #tempQueueLowBnd,
DEST_INDEX := UDINT_TO_DINT(#itemIndex) - #tempItemLowBnd,
DEST => #item);
END_IF;
#statHeadIndex += UDINT_TO_DINT(#itemLen);
IF #statHeadIndex >= #tempQueueSize THEN
#statHeadIndex := #statHeadIndex - #tempQueueSize;
#statReturn := FALSE;
END_IF;
END_IF;
END_REGION
//复位
IF #reset THEN
#statTailIndex := 0;
#statHeadIndex := 0;
#statQueueUsed := 0;
#statReturn := false;
END_IF;
//队列元素数量统计,尾指针没有翻转和翻转两种情况
IF #statReturn = FALSE THEN
#statQueueUsed := #statTailIndex - #statHeadIndex;
ELSE
#statQueueUsed := #tempQueueSize - (#statHeadIndex - 1) + #statTailIndex - 1;
END_IF;
#statQueueUnused := #tempQueueSize - #statQueueUsed;
#queueUsed := #statQueueUsed;
#queueUnused := #statQueueUnused;
#error := FALSE;
#status := #NO_ERROR;