• 正文
  • 相关推荐
申请入驻 产业图谱

大众VASS06标准FB550LIFO后进先出缓存功能块深度解读

06/18 10:23
766
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

该数据块提供了一个滑块寄存器(LIFO,后进先出),最多包含50个存储寄存器。每个寄存器都具有格式 DWORD。

功能块说明:

当LIFO未满时,使用输入端IN的上升沿将一个数据项存入LIFO。

当LIFO不为空时,使用输入端Out的上升沿将一个数据项取出。

注意:输入端IN和OUT不能进入同一周期,否则不会执行任何动作。储存和取出功能是相互锁定的。

可以从可视化干预数据 array。可以插入、覆盖或删除数据。

其中将待处理的元素添加到标记位置,进行处理或删除。在插入时将所有后面的数据向前移动一个存储位置,并且使得指针递增,在删除时则将所有后面的数据记录向后移动一个位置。

在可视化中编辑某个数据记录的时间受到监控。如果带有按钮“更改”、“插入”、“删除”或“取消”的输入端在20秒后仍未结束,则SPS将撤回对数据项的处理。

LIFO功能块详细解读:

1、功能块调用:

2、全部代码:

REGION (/* Aenderungsjournal */)
(*
******************************************************************************************
**  Copyright  2016             SIEMENS AG D-90475 Nuernberg                            **
**  All Rights Reserved         VOLKSWAGEN AG, 38436 Wolfsburg                          **
**                              AUDI AG, D-85045 Ingolstadt                             **
******************************************************************************************
    Datum       Version     Autor       Beschreibung                                    
----------------------------------------------------------------------------------------------------------------
    06.01.22    1.5.00      Gruber      Vorbereitung fuer Mehrsprachige Kommentare durchgefuehrt
    28.01.19    1.4.00      Schulz      Korrektur: Button "Abbrechen" wird auch eingeblendet
                                        bei FRG_Korr; Zuweisung dwvisuwerte
    19.12.18    1.2.00      VASS_V6     Bildbaustein neu
    12.04.18    1.1.00      VASS_V6     TIA Startversion
    17.01.18    0.0.07      Waldeck     VASS-Merker nach DB_ARG verschoben
    13.02.17    0.0.00      Waldeck     Migration TIA V14
    05.03.12    3.0.00      Jablonski   Uebernahme in VASS_Standard aus V1.6
****************************************************************************************
*)
END_REGION

(/* LIFO fuer die Zwischenspeicherung von Pufferdaten */)
(/* Ruecksetzen der Befehle durch externe Quittierung */)

REGION (/* Programm */)
(/* Umladen der Nutzdaten */)
    FOR #iZeiger := 0 TO 50 DO
        #"HMI-UDT".arVisuWerte[#iZeiger].D_Word := #Typ_Daten[#iZeiger];
    END_FOR;

    #iZeiger := BYTE_TO_INT(#"HMI-UDT".arVisuWerte[0].D_Word.%B2);

(/* Laengenpruefung */)
    #iLaenge := #Laenge;
    IF #iLaenge < 1 OR #iLaenge > 50 THEN
        #iLaenge := 50;
    END_IF;

(/* Grenzen des LIFOs ueberpruefen */)
    #xLeer := (#iZeiger < 1);
    #xVoll := (#iZeiger >= #iLaenge);

(/* Einspeichern eines neuen Datensatzes */)
    #R_TRIG_In(CLK := #In AND NOT #xVoll);
    IF #R_TRIG_In.Q AND NOT #In_Done THEN
        #iZeiger := #iZeiger + 1;
        #"HMI-UDT".arVisuWerte[#iZeiger].D_Word := #Daten_In;
        #In_Done := True;
    END_IF;

(/* Austragen eines Datensatzes*) */)
    #R_TRIG_Out(CLK := #Out AND (#In_Done OR NOT #In) AND NOT #xLeer);
    IF #R_TRIG_Out.Q AND NOT #Out_Done THEN
        #Daten_Out := #"HMI-UDT".arVisuWerte[#iZeiger].D_Word;
    (/* Freigewordenes Datenfeld abloeschen und #iZeiger anpassen */) 
        #"HMI-UDT".arVisuWerte[#iZeiger].D_Word := #dwLeerdaten;
        #iZeiger := #iZeiger - 1;
        #Out_Done := True;
    END_IF;

(/* #Anzahl arVisuWerte #In Puffer */)
    #Anzahl := #iZeiger;

    (/* - Sichtbarkeit der Buttons zuruecksetzen */)
    #"HMI-UDT".dwVisuWerte1.%X0 := FALSE;
    #"HMI-UDT".dwVisuWerte1.%X1 := FALSE;
    #"HMI-UDT".dwVisuWerte1.%X2 := FALSE;
    #"HMI-UDT".dwVisuWerte1.%X3 := FALSE;

    (/* - Setzen der Buttons-Sichtbarkeit */)
    IF #Frg_Korr THEN
        (/* Wenn Freigabe, dann */) 
        IF (#iZeiger <= 0) THEN
            (/* Wenn kein Element */) 
            #"HMI-UDT".arVisuWerte[0].D_Word.%X25 := True;                               (/* Aendern */)
            #"HMI-UDT".arVisuWerte[0].D_Word.%X26 := True;                               (/* Loeschen */)

            #"HMI-UDT".dwVisuWerte1.%X1 := True;                                         (/* Aendern */)
            #"HMI-UDT".dwVisuWerte1.%X2 := True;                                         (/* Loeschen */)
        END_IF;

        IF (#iZeiger >= #iLaenge) THEN
            (/* Wenn #Voll */) 
            #"HMI-UDT".arVisuWerte[0].D_Word.%X24 := True;                               (/* Einfuegen */)
            #"HMI-UDT".dwVisuWerte1.%X0 := True;                                         (/* Einfuegen */)
        END_IF;

    ELSE
        (/* Wenn kein Freigabe: */)
        #"HMI-UDT".arVisuWerte[0].D_Word := #"HMI-UDT".arVisuWerte[0].D_Word AND DWORD#16#FFFFFF00;
        #"HMI-UDT".dwVisuWerte1.%B0 := Byte#16#F;                                        (/* Alle Unsichtbar */)
    END_IF;

    IF NOT #Frg_Korr THEN
        #"HMI-UDT".dwVisuTasten2 := DWORD#0;
        #"HMI-UDT".dwVisuTasten2.%B2 := Byte#0;                                          (/* Position (1..50) */)
        #"HMI-UDT".dwVisuTasten2.%B3 := Byte#0;                                          (/* Befehl (1: Einfuegen 2: Aendern 3: Loeschen) */)
    END_IF;

(/* Typkennung fuer Lifo */)
    #"HMI-UDT".arVisuWerte[0].D_Word.%X2 := True;
    #bBefehl := #"HMI-UDT".dwVisuTasten2.%B3;                                            (/* Befehl (1: Einfuegen 2: Aendern 3: Loeschen) */)
    #iVisuZeiger := BYTE_TO_INT(#"HMI-UDT".dwVisuTasten2.%B2);                           (/* Position (1..50) */)

    REGION (/* Visutasten */)
(/* Schreibbefehle von der Visualisierung ueberwachen */)

        IF "DB_ARG".PC_AKTIV = DWORD#16#00000000 OR NOT #Frg_Korr THEN
            #bBefehl := Byte#0;
            #iVisuZeiger := INT#0;
        END_IF;


(/* Pruefung auf gueltige Werte */)
        IF #iVisuZeiger > 0 AND #iVisuZeiger <= 50 THEN

  (/* Einfuegen eines neuen Datensatzes aus der Visu */)
            IF #bBefehl = Byte#1 AND NOT #xVoll THEN
                #"HMI-UDT".dwVisuWerte1.%X7 := NOT #"HMI-UDT".dwVisuWerte1.%X7;
                IF #iVisuZeiger <= #iZeiger THEN
                    #iZeiger := #iZeiger + 1;
                    #iHM_Zaehler1 := #iZeiger;
                    REPEAT
                        #iHM_Zaehler2 := #iHM_Zaehler1 - 1;
                        #"HMI-UDT".arVisuWerte[#iHM_Zaehler1] := #"HMI-UDT".arVisuWerte[#iHM_Zaehler2];
                        #iHM_Zaehler1 := #iHM_Zaehler1 - 1;
                    UNTIL #iHM_Zaehler2 = #iVisuZeiger
                    END_REPEAT;
                    #"HMI-UDT".arVisuWerte[#iVisuZeiger].D_Word := #"HMI-UDT".dwVisuTasten1;
                ELSE
                    #iZeiger := #iZeiger + 1;
                    #"HMI-UDT".arVisuWerte[#iZeiger].D_Word := #"HMI-UDT".dwVisuTasten1;
                END_IF;
                #"HMI-UDT".dwVisuTasten2.%B3 := Byte#0;
                #"HMI-UDT".dwVisuTasten2.%B2 := Byte#0;
            END_IF;

    (/* Ueberschreiben eines Datensatzes aus der Visualisierung */)
            IF #bBefehl = Byte#2 AND #iVisuZeiger <= #iZeiger THEN
                #"HMI-UDT".arVisuWerte[#iVisuZeiger].D_Word := #"HMI-UDT".dwVisuTasten1;
                #"HMI-UDT".dwVisuTasten2.%B3 := Byte#0;
                #"HMI-UDT".dwVisuTasten2.%B2 := Byte#0;
            END_IF;

    (/* Loeschen eines Datensatzes aus der Visualisierung */)
            IF #bBefehl = Byte#3 AND #iVisuZeiger <= #iZeiger THEN
                #iZeiger := #iZeiger - 1;
                #iHM_Zaehler2 := #iVisuZeiger;                                           (/* Initialisierung, fuer iVisuZeiger > iZeiger */)
                FOR #iHM_Zaehler1 := #iVisuZeiger TO #iZeiger DO
                    #iHM_Zaehler2 := #iHM_Zaehler1 + 1;
                    #"HMI-UDT".arVisuWerte[#iHM_Zaehler1] := #"HMI-UDT".arVisuWerte[#iHM_Zaehler2];
                END_FOR;
                #"HMI-UDT".arVisuWerte[#iHM_Zaehler2].D_Word := #dwLeerdaten;
                #"HMI-UDT".dwVisuTasten2.%B3 := Byte#0;
                #"HMI-UDT".dwVisuTasten2.%B2 := Byte#0;
            END_IF;
    (/* Aenderung des Ausgangs  #Daten_Out */) 
        ELSIF #iVisuZeiger = 55 AND #bBefehl = Byte#2 THEN
            #Daten_Out := #"HMI-UDT".dwVisuTasten1;
            #"HMI-UDT".dwVisuTasten2.%B3 := Byte#0;
            #"HMI-UDT".dwVisuTasten2.%B2 := Byte#0;
        END_IF;
    END_REGION
END_REGION


(/* arVisuWerte fuer Visu aufbereiten------------------------------------------------- */)
REGION (/* Farbanimation */)
(/* ********Farbcodetabelle********** */)
(/* BK=Black/Schwarz, BU=Blue/Blau */)
(/* GN=Green/Gruen, GR=Gray/Grau   */)
(/* LT=Light/Hell, WH=White/Weiss  */)
(/* YE=Yellow/Gelb, RD=Red/Rot     */)
(/* st=Statisch, bl=blinkend       */)
(/* HEX Flaechenfarben  Textfarben */)
(/* 00: Flaeche GR   st Text BK st */)
(/* 01: nicht sichtbar             */)
(/* 02: Flaeche GN   st Text BK st */)
(/* 03: Flaeche BU   st Text WH st */)
(/* 04: Flaeche RD   st Text WH st */)
(/* 05: Flaeche LTBU st Text WH st */)
(/* 06: Flaeche YE   st Text BK st */)
(/* 07: Flaeche LTBU st Text YE st */)
(/* 08: Flaeche GR   st Text GN st */)
(/* 09: Flaeche GR   st Text BU st */)
(/* 0A: Flaeche GR   st Text YE st */)
(/* 0B: Flaeche GN   bl Text BK st */)
(/* 0C: Flaeche BU   bl Text WH bl */)
(/* 0D: Flaeche RD   bl Text WH bl */)
(/* 0E: Flaeche LTBU bl Text WH bl */)
(/* 0F: Flaeche YE   bl Text BK st */)
(/* 10: Flaeche GR   st Text GN bl */)
(/* 11: Flaeche GR   st Text BU bl */)
(/* 12: Flaeche GR   st Text YE bl */)
(/* 13: Flaeche GN   st Text YE bl */)
(/* 14: Flaeche BU   st Text YE bl */)
(/* 15: Flaeche LTBU st Text YE bl */)
(/* 16: Flaeche LTBU bl Text YE bl */)
(* ********************************)

    #"HMI-UDT".arVisuWerte[0].D_Word.%X0 := #Frg_Korr;
    #"HMI-UDT".dwVisuWerte1.%B3 := BOOL_TO_BYTE(#Frg_Korr);


    (/* - (#Laenge) */)
    #"HMI-UDT".arVisuWerte[0].D_Word.%B1 := INT_TO_BYTE(#iLaenge);
    #"HMI-UDT".dwVisuWerte1.%B2 := INT_TO_BYTE(#iLaenge);

    (/* - (#iZeiger) */)
    #"HMI-UDT".arVisuWerte[0].D_Word.%B2 := INT_TO_BYTE(#iZeiger);
    #"HMI-UDT".dwVisuWerte1.%B1 := INT_TO_BYTE(#iZeiger);
END_REGION

REGION (/* Ausgaben */)
(/* Umladen der Nutzdaten */) 
    FOR #iZeiger := 0 TO 50 DO
        #Typ_Daten[#iZeiger] := #"HMI-UDT".arVisuWerte[#iZeiger].D_Word;
    END_FOR;

(/* Status ausgeben */)
    #Leer := #xLeer;
    #Voll := #xVoll;
END_REGION

(/* Ende */)   

3、功能块深度解读:

1. 功能块概述

这是一个**LIFO(Last In First Out,后进先出)**数据缓冲区功能块,主要用于:

  • 数据的临时存储和管理
  • HMI人机界面的数据交互
  • 支持可视化操作(插入、修改、删除)

2. 输入输出接口分析

输入参数(Input)

  • In:

Bool - 数据输入触发信号

  • Out:

Bool - 数据输出触发信号

  • Daten_In:

DWord - 要存入LIFO的数据

  • Laenge:

Int - LIFO缓冲区长度设置

  • Frg_Korr:

Bool - 修正/编辑权限标志

输出参数(Output)

  • Leer:

Bool - LIFO为空标志

  • Voll:

Bool - LIFO已满标志

  • Anzahl:

Int - 当前LIFO中数据个数

  • Daten_Out:

DWord - 从LIFO输出的数据

输入输出参数(InOut)

  • In_Done:

Bool - 输入完成标志

  • Out_Done:

Bool - 输出完成标志

  • Typ_Daten:

Array[0..50] of DWord - 数据类型数组

3. 核心程序逻辑解读

3.1 数据初始化和长度检查

(/* 数据载入 */)
FOR #iZeiger := 0 TO 50 DO
    #"HMI-UDT".arVisuWerte[#iZeiger].D_Word := #Typ_Daten[#iZeiger];
END_FOR;

#iZeiger := BYTE_TO_INT(#"HMI-UDT".arVisuWerte[0].D_Word.%B2);

(/* 长度检查 */)
#iLaenge := #Laenge;
IF #iLaenge < 1 OR #iLaenge > 50 THEN
    #iLaenge := 50;
END_IF;

解读:

  • 将外部数据数组复制到内部HMI数据结构
  • 从数据的第2字节获取当前指针位置
  • 限制LIFO长度在1-50范围内,超出则默认为50

3.2 LIFO状态检查

(/* LIFO边界检查 */)
#xLeer := (#iZeiger < 1);
#xVoll := (#iZeiger >= #iLaenge);

解读:

  • xLeer:

当指针小于1时,LIFO为空

  • xVoll:

当指针大于等于设定长度时,LIFO已满

3.3 数据入栈操作

(/* 存入新数据记录 */)
#R_TRIG_In(CLK := #In AND NOT #xVoll);
IF #R_TRIG_In.Q AND NOT #In_Done THEN
    #iZeiger := #iZeiger + 1;
    #"HMI-UDT".arVisuWerte[#iZeiger].D_Word := #Daten_In;
    #In_Done := True;
END_IF;

解读:

  • 使用上升沿检测(R_TRIG)确保只在In信号上升沿时执行一次
  • 条件:In信号有效 且 LIFO未满 且 未完成输入
  • 执行:指针加1,存入数据,设置完成标志

3.4 数据出栈操作

(/* 取出数据记录 */)
#R_TRIG_Out(CLK := #Out AND (#In_Done OR NOT #In) AND NOT #xLeer);
IF #R_TRIG_Out.Q AND NOT #Out_Done THEN
    #Daten_Out := #"HMI-UDT".arVisuWerte[#iZeiger].D_Word;
    (/* 清除已释放的数据字段并调整指针 */)
    #"HMI-UDT".arVisuWerte[#iZeiger].D_Word := #dwLeerdaten;
    #iZeiger := #iZeiger - 1;
    #Out_Done := True;
END_IF;

解读:

  • 条件:Out信号有效 且 (输入已完成或无输入) 且 LIFO非空
  • 执行:输出栈顶数据,清空该位置,指针减1,设置完成标志

4. HMI可视化控制

4.1 按钮可见性控制

(/* 重置按钮可见性 */)
#"HMI-UDT".dwVisuWerte1.%X0 := FALSE;  // 插入按钮
#"HMI-UDT".dwVisuWerte1.%X1 := FALSE;  // 修改按钮
#"HMI-UDT".dwVisuWerte1.%X2 := FALSE;  // 删除按钮
#"HMI-UDT".dwVisuWerte1.%X3 := FALSE;

(/* 根据权限和状态设置按钮可见性 */)
IF #Frg_Korr THEN
    IF (#iZeiger <= 0) THEN
        // LIFO空时显示修改和删除按钮
        #"HMI-UDT".arVisuWerte[0].D_Word.%X25 := True;  // 修改
        #"HMI-UDT".arVisuWerte[0].D_Word.%X26 := True;  // 删除
    END_IF;

    IF (#iZeiger >= #iLaenge) THEN
        // LIFO满时显示插入按钮
        #"HMI-UDT".arVisuWerte[0].D_Word.%X24 := True;  // 插入
    END_IF;
END_IF;

4.2 HMI操作处理

#bBefehl := #"HMI-UDT".dwVisuTasten2.%B3;        // 命令类型
#iVisuZeiger := BYTE_TO_INT(#"HMI-UDT".dwVisuTasten2.%B2);  // 操作位置

(/* 插入操作 - 命令=1 */)
IF #bBefehl = Byte#1 AND NOT #xVoll THEN
    IF #iVisuZeiger <= #iZeiger THEN
        // 在指定位置插入,需要移动后续数据
        #iZeiger := #iZeiger + 1;
        #iHM_Zaehler1 := #iZeiger;
        REPEAT
            #iHM_Zaehler2 := #iHM_Zaehler1 - 1;
            #"HMI-UDT".arVisuWerte[#iHM_Zaehler1] := #"HMI-UDT".arVisuWerte[#iHM_Zaehler2];
            #iHM_Zaehler1 := #iHM_Zaehler1 - 1;
        UNTIL #iHM_Zaehler2 = #iVisuZeiger
        END_REPEAT;
        #"HMI-UDT".arVisuWerte[#iVisuZeiger].D_Word := #"HMI-UDT".dwVisuTasten1;
    ELSE
        // 在末尾插入
        #iZeiger := #iZeiger + 1;
        #"HMI-UDT".arVisuWerte[#iZeiger].D_Word := #"HMI-UDT".dwVisuTasten1;
    END_IF;
END_IF;

(/* 修改操作 - 命令=2 */)
IF #bBefehl = Byte#2 AND #iVisuZeiger <= #iZeiger THEN
    #"HMI-UDT".arVisuWerte[#iVisuZeiger].D_Word := #"HMI-UDT".dwVisuTasten1;
END_IF;

(/* 删除操作 - 命令=3 */)
IF #bBefehl = Byte#3 AND #iVisuZeiger <= #iZeiger THEN
    #iZeiger := #iZeiger - 1;
    // 将后续数据前移
    FOR #iHM_Zaehler1 := #iVisuZeiger TO #iZeiger DO
        #iHM_Zaehler2 := #iHM_Zaehler1 + 1;
        #"HMI-UDT".arVisuWerte[#iHM_Zaehler1] := #"HMI-UDT".arVisuWerte[#iHM_Zaehler2];
    END_FOR;
    #"HMI-UDT".arVisuWerte[#iHM_Zaehler2].D_Word := #dwLeerdaten;
END_IF;

5. 颜色动画和状态显示

程序包含详细的颜色编码表,用于HMI界面的状态显示:

颜色代码表:
00: 灰色背景,黑色文字(静态)
01: 不可见
02: 绿色背景,黑色文字(静态)
03: 蓝色背景,白色文字(静态)
04: 红色背景,白色文字(静态)
05: 浅蓝背景,白色文字(静态)
06: 黄色背景,黑色文字(静态)
...
0B-0F: 闪烁效果
10-16: 文字闪烁效果

6. 数据输出和状态更新

(/* 输出数据更新 */)
FOR #iZeiger := 0 TO 50 DO
    #Typ_Daten[#iZeiger] := #"HMI-UDT".arVisuWerte[#iZeiger].D_Word;
END_FOR;

(/* 状态输出 */)
#Leer := #xLeer;
#Voll := #xVoll;
#Anzahl := #iZeiger;

7. 主要特点总结

1 标准LIFO操作:

支持后进先出的数据存取

2 HMI集成:

完整的人机界面交互支持

3 可视化操作:

支持插入、修改、删除操作

4 权限控制:

通过Frg_Korr参数控制编辑权限

5 状态反馈:

提供空、满状态和数据数量信息

6 错误防护:

包含边界检查和参数验证

7 多语言支持:

代码注释支持多语言

这个功能块非常适合用于工业自动化中需要数据缓存和人机交互的场景,如配方管理、报警记录、操作日志等应用。

大众汽车

大众汽车

大众汽车集团是中国汽车工业最早、最成功的国际合作伙伴之一,伴随中国汽车工业成长近四十年。大众汽车集团(中国)始终致力于成为中国社会最值得信赖的合作伙伴,在为消费者提供可靠、高质量产品与服务的同时,更以支持中国社会的可持续发展作为重要己任。

大众汽车集团是中国汽车工业最早、最成功的国际合作伙伴之一,伴随中国汽车工业成长近四十年。大众汽车集团(中国)始终致力于成为中国社会最值得信赖的合作伙伴,在为消费者提供可靠、高质量产品与服务的同时,更以支持中国社会的可持续发展作为重要己任。收起

查看更多

相关推荐