該數(shù)據(jù)塊提供了一個滑塊寄存器(LIFO,后進(jìn)先出),最多包含50個存儲寄存器。每個寄存器都具有格式 DWORD。
功能塊說明:
當(dāng)LIFO未滿時,使用輸入端IN的上升沿將一個數(shù)據(jù)項存入LIFO。
當(dāng)LIFO不為空時,使用輸入端Out的上升沿將一個數(shù)據(jù)項取出。
注意:輸入端IN和OUT不能進(jìn)入同一周期,否則不會執(zhí)行任何動作。儲存和取出功能是相互鎖定的。
可以從可視化干預(yù)數(shù)據(jù) array??梢圆迦?、覆蓋或刪除數(shù)據(jù)。
其中將待處理的元素添加到標(biāo)記位置,進(jìn)行處理或刪除。在插入時將所有后面的數(shù)據(jù)向前移動一個存儲位置,并且使得指針遞增,在刪除時則將所有后面的數(shù)據(jù)記錄向后移動一個位置。
在可視化中編輯某個數(shù)據(jù)記錄的時間受到監(jiān)控。如果帶有按鈕“更改”、“插入”、“刪除”或“取消”的輸入端在20秒后仍未結(jié)束,則SPS將撤回對數(shù)據(jù)項的處理。
LIFO功能塊詳細(xì)解讀:
1、功能塊調(diào)用:
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,后進(jìn)先出)**數(shù)據(jù)緩沖區(qū)功能塊,主要用于:
- 數(shù)據(jù)的臨時存儲和管理
- HMI人機界面的數(shù)據(jù)交互
- 支持可視化操作(插入、修改、刪除)
2. 輸入輸出接口分析
輸入?yún)?shù)(Input)
- In:
Bool - 數(shù)據(jù)輸入觸發(fā)信號
- Out:
Bool - 數(shù)據(jù)輸出觸發(fā)信號
- Daten_In:
DWord - 要存入LIFO的數(shù)據(jù)
- Laenge:
Int - LIFO緩沖區(qū)長度設(shè)置
- Frg_Korr:
Bool - 修正/編輯權(quán)限標(biāo)志
輸出參數(shù)(Output)
- Leer:
Bool - LIFO為空標(biāo)志
- Voll:
Bool - LIFO已滿標(biāo)志
- Anzahl:
Int - 當(dāng)前LIFO中數(shù)據(jù)個數(shù)
- Daten_Out:
DWord - 從LIFO輸出的數(shù)據(jù)
輸入輸出參數(shù)(InOut)
- In_Done:
Bool - 輸入完成標(biāo)志
- Out_Done:
Bool - 輸出完成標(biāo)志
- Typ_Daten:
Array[0..50] of DWord - 數(shù)據(jù)類型數(shù)組
3. 核心程序邏輯解讀
3.1 數(shù)據(jù)初始化和長度檢查
(/* 數(shù)據(jù)載入 */)
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;
解讀:
- 將外部數(shù)據(jù)數(shù)組復(fù)制到內(nèi)部HMI數(shù)據(jù)結(jié)構(gòu)
- 從數(shù)據(jù)的第2字節(jié)獲取當(dāng)前指針位置
- 限制LIFO長度在1-50范圍內(nèi),超出則默認(rèn)為50
3.2 LIFO狀態(tài)檢查
(/* LIFO邊界檢查 */)
#xLeer := (#iZeiger < 1);
#xVoll := (#iZeiger >= #iLaenge);
解讀:
- xLeer:
當(dāng)指針小于1時,LIFO為空
- xVoll:
當(dāng)指針大于等于設(shè)定長度時,LIFO已滿
3.3 數(shù)據(jù)入棧操作
(/* 存入新數(shù)據(jù)記錄 */)
#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信號上升沿時執(zhí)行一次
- 條件:In信號有效 且 LIFO未滿 且 未完成輸入
- 執(zhí)行:指針加1,存入數(shù)據(jù),設(shè)置完成標(biāo)志
3.4 數(shù)據(jù)出棧操作
(/* 取出數(shù)據(jù)記錄 */)
#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;
(/* 清除已釋放的數(shù)據(jù)字段并調(diào)整指針 */)
#"HMI-UDT".arVisuWerte[#iZeiger].D_Word := #dwLeerdaten;
#iZeiger := #iZeiger - 1;
#Out_Done := True;
END_IF;
解讀:
- 條件:Out信號有效 且 (輸入已完成或無輸入) 且 LIFO非空
- 執(zhí)行:輸出棧頂數(shù)據(jù),清空該位置,指針減1,設(shè)置完成標(biāo)志
4. HMI可視化控制
4.1 按鈕可見性控制
(/* 重置按鈕可見性 */)
#"HMI-UDT".dwVisuWerte1.%X0 := FALSE; // 插入按鈕
#"HMI-UDT".dwVisuWerte1.%X1 := FALSE; // 修改按鈕
#"HMI-UDT".dwVisuWerte1.%X2 := FALSE; // 刪除按鈕
#"HMI-UDT".dwVisuWerte1.%X3 := FALSE;
(/* 根據(jù)權(quán)限和狀態(tài)設(shè)置按鈕可見性 */)
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
// 在指定位置插入,需要移動后續(xù)數(shù)據(jù)
#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;
// 將后續(xù)數(shù)據(jù)前移
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. 顏色動畫和狀態(tài)顯示
程序包含詳細(xì)的顏色編碼表,用于HMI界面的狀態(tài)顯示:
顏色代碼表:
00: 灰色背景,黑色文字(靜態(tài))
01: 不可見
02: 綠色背景,黑色文字(靜態(tài))
03: 藍(lán)色背景,白色文字(靜態(tài))
04: 紅色背景,白色文字(靜態(tài))
05: 淺藍(lán)背景,白色文字(靜態(tài))
06: 黃色背景,黑色文字(靜態(tài))
...
0B-0F: 閃爍效果
10-16: 文字閃爍效果
6. 數(shù)據(jù)輸出和狀態(tài)更新
(/* 輸出數(shù)據(jù)更新 */)
FOR #iZeiger := 0 TO 50 DO
#Typ_Daten[#iZeiger] := #"HMI-UDT".arVisuWerte[#iZeiger].D_Word;
END_FOR;
(/* 狀態(tài)輸出 */)
#Leer := #xLeer;
#Voll := #xVoll;
#Anzahl := #iZeiger;
7. 主要特點總結(jié)
1 標(biāo)準(zhǔn)LIFO操作:
支持后進(jìn)先出的數(shù)據(jù)存取
2 HMI集成:
完整的人機界面交互支持
3 可視化操作:
支持插入、修改、刪除操作
4 權(quán)限控制:
通過Frg_Korr參數(shù)控制編輯權(quán)限
5 狀態(tài)反饋:
提供空、滿狀態(tài)和數(shù)據(jù)數(shù)量信息
6 錯誤防護(hù):
包含邊界檢查和參數(shù)驗證
7 多語言支持:
代碼注釋支持多語言
這個功能塊非常適合用于工業(yè)自動化中需要數(shù)據(jù)緩存和人機交互的場景,如配方管理、報警記錄、操作日志等應(yīng)用。