【SCL编程案例】先入先出 FIFO 功能块

已锁定

西门龍霆

  • 帖子

    35
  • 精华

    0
  • 被关注

    3

论坛等级:侠客

注册时间:2016-11-28

白金 白金 如何晋级?

【SCL编程案例】先入先出 FIFO 功能块

1511

1

2025-09-05 09:37:47

FUNCTION_BLOCK "fbFIFO"


{ S7_Optimized_Access := 'TRUE' }


VERSION : 0.1


   VAR_INPUT

      bInPush { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; // 入队命令

      vInPushElement : Variant; // 入队元素

      bInPeek { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; // 查看队首命令

      bInPop { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; // 出队命令

      bInClear { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; // 清空队列命令

   END_VAR


   VAR_OUTPUT

      iOutErrorCode { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int; // 错误码输出

      diOutCount { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : DInt; // 队列元素数量

      bOutQueueFull { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; // 队列满标志

      bOutQueueEmpty { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; // 队列空标志

   END_VAR


   VAR_IN_OUT

      vInOutQueue : Variant; // 队列数组

      vInOutPopPeekElement : Variant; // 出队/查看元素

   END_VAR


   VAR

      diPushIndex { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : DInt; // 入队索引

      diPopIndex { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : DInt; // 出队索引

      diCount { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : DInt; // 队列计数

      ONS_Push { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; // 入队上升沿检测

      ONS_Pop { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; // 出队上升沿检测

      ONS_Peek { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; // 查看上升沿检测

      ONS_Clear { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; // 清空上升沿检测

   END_VAR


   VAR_TEMP

      iTemp : Int; // 临时变量

      diQueueSize : DInt; // 队列大小

      byTemp : Byte; // 临时变量

   END_VAR


   VAR CONSTANT

      ciError_None : Bool; // 无错误

      ciError_InvalidQueueSize : Int := 1; // 队列大小无效

      ciError_InvalidQueueTypes : Int := 2; // 队列类型不一致

      ciError_MultipleCommandsReceived : Int := 3; // 同时收到多个命令

   END_VAR


BEGIN


// 使用Variant实现的先进先出队列(FIFO)


// 获取队列数组的总元素数

#diQueueSize := CountOfElements(#vInOutQueue);


// 队列大小为0,说明不是数组,队列对象无效

IF (#diQueueSize <= 0) THEN

    #iOutErrorCode := #ciError_InvalidQueueSize;

    RETURN;

END_IF;


// 检查队列元素类型是否一致

IF (TypeOfElements(#vInOutQueue) <> TypeOf(#vInPushElement) OR TypeOf(#vInOutPopPeekElement) <> TypeOf(#vInPushElement)) THEN

    #iOutErrorCode := #ciError_InvalidQueueTypes;

    RETURN;

END_IF;


// 检查同一时刻只允许一个命令(push和pop/peek可同时)

#byTemp := BOOL_TO_BYTE(#bInPop) +

BOOL_TO_BYTE(#bInPeek) +

BOOL_TO_BYTE(#bInClear);


IF (#byTemp > 1 OR (#bInPush AND #bInClear)) THEN

    #iOutErrorCode := #ciError_MultipleCommandsReceived;

    RETURN;

END_IF;


// 入队操作,队列未满时执行

IF (#bInPush AND NOT #ONS_Push AND #diCount < #diQueueSize) THEN

    #iTemp := MOVE_BLK_VARIANT(SRC := #vInPushElement, COUNT := 1, SRC_INDEX := 0, DEST_INDEX := #diPushIndex, DEST => #vInOutQueue);

    #diCount += 1;

    #diPushIndex := (#diPushIndex + 1) MOD #diQueueSize;

END_IF;


// 出队或查看操作,队列非空时执行

IF ((#bInPop AND NOT #ONS_Pop) OR (#bInPeek AND NOT #ONS_Peek) AND #diCount > 0) THEN

    #iTemp := MOVE_BLK_VARIANT(SRC := #vInOutQueue, COUNT := 1, SRC_INDEX := #diPopIndex, DEST_INDEX := 0, DEST => #vInOutPopPeekElement);

    IF (#bInPop) THEN

        #diCount -= 1;

        #diPopIndex := (#diPopIndex + 1) MOD #diQueueSize;

    END_IF;

// 清空队列,重置索引

ELSIF (#bInClear AND NOT #ONS_Clear) THEN

    #diCount := 0;

    #diPushIndex := 0;

    #diPopIndex := 0;

END_IF;


// 设置队列满/空标志

IF (#diCount >= #diQueueSize) THEN

    #bOutQueueFull := TRUE;

    #bOutQueueEmpty := FALSE;

ELSIF (#diCount <= 0) THEN

    #bOutQueueFull := FALSE;

    #bOutQueueEmpty := TRUE;

ELSE

    #bOutQueueFull := FALSE;

    #bOutQueueEmpty := FALSE;

END_IF;


// 记录本周期命令状态,用于上升沿检测

#ONS_Pop := #bInPop;

#ONS_Peek := #bInPeek;

#ONS_Push := #bInPush;

#ONS_Clear := #bInClear;


// 清除错误码并输出队列计数

#iOutErrorCode := 0;

#diOutCount := #diCount;


END_FUNCTION_BLOCK


【SCL编程案例】先入先出 FIFO 功能块 已锁定
编辑推荐: 关闭

请填写推广理由:

本版热门话题

SIMATIC S7-1500系列

共有11207条技术帖

相关推荐

热门标签

相关帖子推荐

guzhang

恭喜,你发布的帖子

评为精华帖!

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

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

  • 分享

  • 只看
    楼主

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