304 lines
13 KiB
Plaintext
304 lines
13 KiB
Plaintext
FUNCTION "FifoIn" : Void
|
|
TITLE = Datensatz in FIFO-DB eintragen
|
|
{ S7_Optimized_Access := 'FALSE' }
|
|
AUTHOR : IBAE
|
|
FAMILY : Module
|
|
NAME : FifoIn
|
|
//SCL-Portierung des AWL-Bausteins FC80 "FifoIn" (verhaltensgleich).
|
|
//
|
|
//FIFO-Kopf im Schnittstellen-DB ab Byte SSDW:
|
|
// +0 Kopf (Byte, 16#FF = FIFO-Kennung)
|
|
// +1 Datensatzlaenge (Byte, in Worten, 1..128)
|
|
// +2 FifoLaenge (Int, max. Anzahl Datensaetze)
|
|
// +4 Bringzeiger (Int, Byte-Adresse im DB)
|
|
// +6 Holzeiger (Int, Byte-Adresse im DB)
|
|
// +8 Anzahl (Int, eingetragene Datensaetze)
|
|
// +10 Status (Word)
|
|
// +12 Zusatzdaten (4 Worte)
|
|
// +40 Datenbereich, dahinter Endekennung 16#FFEE
|
|
//
|
|
//ABWEICHUNG ZUM AWL-ORIGINAL:
|
|
// - INDATEN ist jetzt VARIANT statt POINTER (S7-1500/SCL). AWL-/SCL-Aufrufer
|
|
// uebergeben weiterhin einen Bereich (z.B. P#M220.0 WORD 6 bzw. ein Symbol).
|
|
// - Registerindirekte DB-Zugriffe sind durch PEEK/POKE ersetzt (DB-Layout identisch).
|
|
// - Erfolg wird wie bisher ueber ENO/BR gemeldet (Aufrufer: JBI bzw. IF ENO).
|
|
VAR_INPUT
|
|
SSDB : Int; // Schnittstellen-DB
|
|
SSDW : Int; // Schnittstellen-1.DW (Byte-Offset des FIFO-Kopfs)
|
|
PARA : Word; // Aufrufparameter (Auftrag / Anzahl Zusatzdaten)
|
|
INDATEN : Variant; // InDaten-Schnittstelle (Datensatz, Datensatzlaenge Worte)
|
|
END_VAR
|
|
|
|
VAR_OUTPUT
|
|
RE_VAL : Byte; // Rueckmeldung (Fehlerbits)
|
|
END_VAR
|
|
|
|
VAR_TEMP
|
|
Kopf : Byte; // Fifo-Kennung (FF)
|
|
Datensatzlaenge : Byte; // Datensatzlaenge in Word (1 - 128)
|
|
FifoLaenge : Int; // Laenge des Fifo (maximale Anzahl der Datensaetze)
|
|
Bringzeiger : Int; // Zeiger, wohin naechster Eintrag gespeichert wird
|
|
Holzeiger : Int; // Zeiger, woher naechste Daten geholt werden
|
|
Anzahl : Int; // Anzahl der Datensaetze (eingetragene)
|
|
Status : Word; // Status des Fifo
|
|
Err : Byte; // Fehlerbits
|
|
Para1 : Byte; // 1.Aufrufparameter
|
|
Para2 : Byte; // 2.Aufrufparameter
|
|
Para21 : Byte; // 2.Aufrufparameter 1.Stelle
|
|
Para22 : Byte; // 2.Aufrufparameter 2.Stelle
|
|
MinBringzeiger : Int; // Minimum Bringzeiger
|
|
MaxBringzeiger : Int; // Maximum Bringzeiger
|
|
SFC_RET_VAL : Int; // Rueckmeldung TEST_DB-/Serialize-Aufruf
|
|
SFC_DB_LENGTH : Word; // DB-Laenge in Bytes
|
|
Fifo_Ende : Int; // Ende des Fifo (Byte-Offset Endekennung)
|
|
Offset : Int; // Offset 1. zu speicherndes Zusatzwort (Bytes)
|
|
SFC_WRITE_PROT : Bool; // DB ist schreibgeschuetzt
|
|
NixSave : Bool; // Status nicht speichern
|
|
tVKE : Bool; // Ergebnis fuer ENO (BR im AWL)
|
|
tDbNo : DInt; // DB-Nummer fuer PEEK/POKE
|
|
tAnzWorte : Int; // Anzahl zu kopierender Worte
|
|
tPos : DInt; // Serialize-Position
|
|
i : Int; // Schleifenzaehler
|
|
tPuffer : Array[0..257] of Byte; // Zwischenpuffer fuer INDATEN
|
|
END_VAR
|
|
|
|
BEGIN
|
|
REGION NW1: Schnittstellen-DB sinnvoll ?
|
|
#tDbNo := INT_TO_DINT(#SSDB);
|
|
|
|
"TEST_DB_TO_ATTR_DB"(DB_Number := INT_TO_WORD(#SSDB),
|
|
RetVal => #SFC_RET_VAL,
|
|
DB_Length => #SFC_DB_LENGTH,
|
|
Write_Prot => #SFC_WRITE_PROT);
|
|
|
|
#NixSave := (#SFC_RET_VAL <> 0) OR #SFC_WRITE_PROT; // Status nicht speichern
|
|
IF #NixSave THEN
|
|
#Err := 16#01; // kein Fifobereich (AWL: Err0)
|
|
GOTO mErr;
|
|
END_IF;
|
|
END_REGION
|
|
|
|
REGION NW2: FIFO-Kopf holen (AWL: Quelle-Pointer + BLKMOV)
|
|
IF #SSDW < 0 OR (#SSDW + 12) > WORD_TO_INT(#SFC_DB_LENGTH) THEN
|
|
#Err.%X1 := TRUE; // Kopf liegt nicht im DB (AWL: SFC20-Fehler, Err1)
|
|
GOTO mErr;
|
|
END_IF;
|
|
|
|
#Kopf := PEEK(area := 16#84, dbNumber := #tDbNo, byteOffset := INT_TO_DINT(#SSDW));
|
|
#Datensatzlaenge := PEEK(area := 16#84, dbNumber := #tDbNo, byteOffset := INT_TO_DINT(#SSDW + 1));
|
|
#FifoLaenge := WORD_TO_INT(PEEK_WORD(area := 16#84, dbNumber := #tDbNo, byteOffset := INT_TO_DINT(#SSDW + 2)));
|
|
#Bringzeiger := WORD_TO_INT(PEEK_WORD(area := 16#84, dbNumber := #tDbNo, byteOffset := INT_TO_DINT(#SSDW + 4)));
|
|
#Holzeiger := WORD_TO_INT(PEEK_WORD(area := 16#84, dbNumber := #tDbNo, byteOffset := INT_TO_DINT(#SSDW + 6)));
|
|
#Anzahl := WORD_TO_INT(PEEK_WORD(area := 16#84, dbNumber := #tDbNo, byteOffset := INT_TO_DINT(#SSDW + 8)));
|
|
#Status := PEEK_WORD(area := 16#84, dbNumber := #tDbNo, byteOffset := INT_TO_DINT(#SSDW + 10));
|
|
|
|
#Err := WORD_TO_BYTE(#Status AND 16#00E0); // Kapitalfehler aus frueheren Aufrufen?
|
|
IF #Err <> 16#00 THEN
|
|
GOTO mErr;
|
|
END_IF;
|
|
END_REGION
|
|
|
|
REGION NW3: Zeigerueberpruefung
|
|
IF #Kopf <> 16#FF THEN // keine Fifokennung
|
|
#NixSave := TRUE;
|
|
#Err := 16#01; // kein Fifobereich
|
|
GOTO mErr;
|
|
END_IF;
|
|
|
|
IF BYTE_TO_INT(#Datensatzlaenge) < 1 OR BYTE_TO_INT(#Datensatzlaenge) > 128 THEN
|
|
#Err := 16#01; // kein Fifobereich
|
|
GOTO mErr;
|
|
END_IF;
|
|
|
|
IF #FifoLaenge < 1 THEN
|
|
#Err := 16#01; // kein Fifobereich
|
|
GOTO mErr;
|
|
END_IF;
|
|
|
|
#MinBringzeiger := #SSDW + 40; // Speichern ab 20.DW
|
|
#MaxBringzeiger := (#FifoLaenge - 1) * BYTE_TO_INT(#Datensatzlaenge) * 2 + 40 + #SSDW;
|
|
#Fifo_Ende := BYTE_TO_INT(#Datensatzlaenge) * 2 + #MaxBringzeiger; // Zeiger Endekennung
|
|
|
|
IF #Fifo_Ende > WORD_TO_INT(#SFC_DB_LENGTH) THEN // Fifo-DB ist zu kurz!
|
|
#Err := 16#01; // kein Fifo-Bereich
|
|
GOTO mErr;
|
|
END_IF;
|
|
|
|
IF PEEK_WORD(area := 16#84, dbNumber := #tDbNo, byteOffset := INT_TO_DINT(#Fifo_Ende)) <> 16#FFEE THEN
|
|
#Err := 16#01; // kein Fifobereich (Endekennung fehlt)
|
|
GOTO mErr;
|
|
END_IF;
|
|
|
|
IF #MinBringzeiger > #Bringzeiger THEN
|
|
// Nur zulaessig, wenn alles in Grundstellung: dann initialisieren
|
|
IF #Bringzeiger <> 0 OR #Holzeiger <> 0 OR #Anzahl <> 0 THEN
|
|
#Err.%X5 := TRUE; // Bringzeiger ist ausserhalb
|
|
GOTO mErr;
|
|
END_IF;
|
|
#Bringzeiger := #MinBringzeiger;
|
|
#Holzeiger := #MinBringzeiger;
|
|
END_IF;
|
|
|
|
IF #Bringzeiger > #MaxBringzeiger THEN
|
|
#Err.%X5 := TRUE; // Bringzeiger ist ausserhalb
|
|
GOTO mErr;
|
|
END_IF;
|
|
|
|
IF (#Bringzeiger = #Holzeiger) AND (#FifoLaenge <> #Anzahl) AND (#Anzahl <> 0) THEN
|
|
#Err.%X7 := TRUE; // Versatz Bring-/Holzeiger
|
|
GOTO mErr;
|
|
END_IF;
|
|
IF (#Bringzeiger <> #Holzeiger) AND ((#FifoLaenge = #Anzahl) OR (#Anzahl = 0)) THEN
|
|
#Err.%X7 := TRUE; // Versatz Bring-/Holzeiger
|
|
GOTO mErr;
|
|
END_IF;
|
|
END_REGION
|
|
|
|
REGION NW4: Nur Zusatzdaten / als 1.Datensatz speichern ?
|
|
#Para1 := WORD_TO_BYTE(SHR(IN := #PARA, N := 8)); // 1.Aufrufparameter
|
|
#Para2 := WORD_TO_BYTE(#PARA); // 2.Aufrufparameter
|
|
|
|
IF #Para1 = 16#02 THEN // Nur Zusatzdaten speichern
|
|
IF #Para2 = 16#00 THEN
|
|
#Err.%X3 := TRUE; // Falscher Aufrufparameter
|
|
GOTO mErr;
|
|
END_IF;
|
|
GOTO mNw06; // Zusatzdaten speichern
|
|
END_IF;
|
|
|
|
IF #Para1 = 16#01 THEN // Als 1.Datensatz speichern
|
|
#Bringzeiger := #MinBringzeiger;
|
|
#Holzeiger := #MinBringzeiger;
|
|
#Anzahl := 0;
|
|
GOTO mNw06; // Zusatz-Daten speichern?
|
|
END_IF;
|
|
END_REGION
|
|
|
|
REGION NW5: Hat Fifo Platz / Datenbereich leer ?
|
|
IF #Anzahl >= #FifoLaenge THEN
|
|
IF #Anzahl = #FifoLaenge THEN
|
|
#Err.%X2 := TRUE; // Fifo ist voll
|
|
ELSE
|
|
#Err.%X7 := TRUE; // Versatz Bring-/Holzeiger
|
|
END_IF;
|
|
GOTO mErr;
|
|
END_IF;
|
|
|
|
// Ziel-Speicherzellen muessen leer (0) sein
|
|
FOR #i := 0 TO BYTE_TO_INT(#Datensatzlaenge) - 1 DO
|
|
IF PEEK_WORD(area := 16#84, dbNumber := #tDbNo,
|
|
byteOffset := INT_TO_DINT(#Bringzeiger + #i * 2)) <> 16#0000 THEN
|
|
#Err.%X4 := TRUE; // Speicherzelle ist belegt
|
|
GOTO mErr;
|
|
END_IF;
|
|
END_FOR;
|
|
END_REGION
|
|
|
|
REGION NW6: Zusatzdaten schreiben (Quelle: Merker ab MB240)
|
|
mNw06: IF #Para2 <> 16#00 THEN
|
|
#Para21 := SHR(IN := #Para2 AND 16#F0, N := 4); // 1.Stelle isolieren (von)
|
|
#Para22 := #Para2 AND 16#0F; // 2.Stelle isolieren (bis)
|
|
|
|
IF (#Para21 > #Para22) // 1.Stelle > 2.Stelle !
|
|
OR (#Para22 > 16#04) // 2.Stelle > 4 !
|
|
OR (#Para21 = 16#00) THEN // 1.Stelle = 0 !
|
|
#Err.%X3 := TRUE; // Falscher Aufrufparameter
|
|
GOTO mErr;
|
|
END_IF;
|
|
|
|
#tAnzWorte := BYTE_TO_INT(#Para22) - BYTE_TO_INT(#Para21) + 1;
|
|
#Offset := (BYTE_TO_INT(#Para21) - 1) * 2; // Offset 1. zu speicherndes Zusatzwort
|
|
|
|
// Quelle: MB240+Offset -> Ziel: DB ab SSDW+12+Offset (ab 6.DW)
|
|
FOR #i := 0 TO #tAnzWorte * 2 - 1 DO
|
|
POKE(area := 16#84, dbNumber := #tDbNo,
|
|
byteOffset := INT_TO_DINT(#SSDW + 12 + #Offset + #i),
|
|
value := PEEK(area := 16#83, dbNumber := 0,
|
|
byteOffset := INT_TO_DINT(240 + #Offset + #i)));
|
|
END_FOR;
|
|
END_IF;
|
|
END_REGION
|
|
|
|
REGION NW7: Fifodaten schreiben
|
|
IF #Para1 = 16#FF THEN // Testsendung: Zeiger nur testweise veraendern
|
|
GOTO mNw08;
|
|
END_IF;
|
|
IF #Para1 = 16#02 THEN // Nur Zusatzdaten speichern: fertig!
|
|
GOTO mEnde;
|
|
END_IF;
|
|
|
|
// INDATEN in Zwischenpuffer holen (AWL: BLKMOV ueber uebergebenen Pointer)
|
|
#tPos := 0;
|
|
#SFC_RET_VAL := Serialize(SRC_VARIANT := #INDATEN, DEST_ARRAY := #tPuffer, POS := #tPos);
|
|
IF (#SFC_RET_VAL <> 0) OR (#tPos < BYTE_TO_INT(#Datensatzlaenge) * 2) THEN
|
|
#Err.%X1 := TRUE; // Kopier-Fehler (AWL: SFC20-Aufruf mit Fehler)
|
|
GOTO mErr;
|
|
END_IF;
|
|
|
|
// Datensatz ab Bringzeiger in FIFO-DB schreiben
|
|
FOR #i := 0 TO BYTE_TO_INT(#Datensatzlaenge) * 2 - 1 DO
|
|
POKE(area := 16#84, dbNumber := #tDbNo,
|
|
byteOffset := INT_TO_DINT(#Bringzeiger + #i),
|
|
value := #tPuffer[#i]);
|
|
END_FOR;
|
|
END_REGION
|
|
|
|
REGION NW8: Bringzeiger, Anzahl erhoehen
|
|
mNw08: #Bringzeiger := BYTE_TO_INT(#Datensatzlaenge) * 2 + #Bringzeiger;
|
|
IF #Bringzeiger > #MaxBringzeiger THEN // Maximum erreicht?
|
|
#Bringzeiger := #MinBringzeiger;
|
|
END_IF;
|
|
|
|
#Anzahl := #Anzahl + 1;
|
|
END_REGION
|
|
|
|
REGION NW9: Versatz Bring-/Holzeiger
|
|
IF (#Bringzeiger = #Holzeiger) AND (#FifoLaenge <> #Anzahl) THEN
|
|
#Err.%X7 := TRUE; // Versatz Bring-/Holzeiger
|
|
GOTO mErr;
|
|
END_IF;
|
|
IF (#Bringzeiger <> #Holzeiger) AND (#FifoLaenge = #Anzahl) THEN
|
|
#Err.%X7 := TRUE; // Versatz Bring-/Holzeiger
|
|
GOTO mErr;
|
|
END_IF;
|
|
END_REGION
|
|
|
|
REGION NW10: Fehlerausgabe / RET_VAL
|
|
mEnde: #tVKE := TRUE; // VKE = 1 ohne Fehler !!!
|
|
GOTO mOk;
|
|
|
|
mErr: #tVKE := FALSE; // VKE = 0 bei Fehler !!!
|
|
|
|
mOk: #RE_VAL := #Err;
|
|
END_REGION
|
|
|
|
#Status := #Status OR BYTE_TO_WORD(#Err);
|
|
|
|
REGION NW11: Fifokopfdaten speichern
|
|
IF #Err.%X0 AND #NixSave THEN // kein gueltiger Fifobereich: nichts speichern
|
|
ENO := #tVKE;
|
|
RETURN;
|
|
END_IF;
|
|
|
|
"MW254" := INT_TO_WORD(#Anzahl - 1); // Uebergabe an FC+1 (da vorher zum Test erhoeht wurde)
|
|
|
|
IF #Para1 = 16#FF THEN // Testsendung: Zeiger wurden nur testweise geaendert!
|
|
ENO := #tVKE;
|
|
RETURN;
|
|
END_IF;
|
|
|
|
// Bringzeiger, Holzeiger, Anzahl, Status in FIFO-Kopf zuruecksichern (ab SSDW+4)
|
|
POKE(area := 16#84, dbNumber := #tDbNo, byteOffset := INT_TO_DINT(#SSDW + 4), value := INT_TO_WORD(#Bringzeiger));
|
|
POKE(area := 16#84, dbNumber := #tDbNo, byteOffset := INT_TO_DINT(#SSDW + 6), value := INT_TO_WORD(#Holzeiger));
|
|
POKE(area := 16#84, dbNumber := #tDbNo, byteOffset := INT_TO_DINT(#SSDW + 8), value := INT_TO_WORD(#Anzahl));
|
|
POKE(area := 16#84, dbNumber := #tDbNo, byteOffset := INT_TO_DINT(#SSDW + 10), value := #Status);
|
|
|
|
"MW248" := INT_TO_WORD(#FifoLaenge); // Uebergabe an FC+1 (fuer Durchlaufspeicher)
|
|
"MW250" := INT_TO_WORD(#Bringzeiger); // Uebergabe an FC+1 (fuer Durchlaufspeicher)
|
|
"MW252" := INT_TO_WORD(#Holzeiger); // Uebergabe an FC+1 (fuer Durchlaufspeicher)
|
|
"MW254" := INT_TO_WORD(#Anzahl); // Uebergabe an FC+1 (fuer Durchlaufspeicher)
|
|
END_REGION
|
|
|
|
ENO := #tVKE; // AWL: SAVE (BR-Bit fuer JBI beim Aufrufer)
|
|
END_FUNCTION
|