461 lines
21 KiB
Plaintext
461 lines
21 KiB
Plaintext
FUNCTION "DatenOut" : Void
|
|
TITLE = Datensatz in Datenliste suchen / lesen / loeschen
|
|
{ S7_Optimized_Access := 'FALSE' }
|
|
AUTHOR : IBAE
|
|
FAMILY : Module
|
|
NAME : DatenOut
|
|
//SCL-Portierung des AWL-Bausteins FC86 "DatenOut" (verhaltensgleich).
|
|
//
|
|
//Datenlisten-Kopf im Datenlisten-DB ab Byte SSDW:
|
|
// +0 Kopf (Byte, 16#DA = Datenliste, 16#DB = Sort-Datenliste)
|
|
// +1 Datensatzlaenge (Byte, in Worten, 1..128)
|
|
// +2 Listenlaenge (Int, max. Anzahl Datensaetze)
|
|
// +4 Stammdaten (Int, Anzahl Suchworte 1..9)
|
|
// +6 IndDB (Word, indizierter DB; nur bei Stammdaten=1)
|
|
// +8 IndDB_Laenge (Int, Laenge indizierter DB in Eintraegen)
|
|
// +10 IndDaten_FC (Int, Wandel-FC-Nummer fuer indizierte Suche)
|
|
// +12 Suchzeiger / letzter Zugriff (Int, Byte-Adresse)
|
|
// +16 AnzahlEintraege (Int)
|
|
// +20 Datenbereich, dahinter Endekennung 16#DAEE bzw. 16#DBEE
|
|
//
|
|
//Aufrufparameter PARA (High-Byte = Para1, Low-Byte = Para2):
|
|
// Para1: 00=suchen, E1=suchen+loeschen, F1=1.Datensatz holen,
|
|
// FF=naechsten Datensatz holen, 02..80=Offset-Suche ab Wort X
|
|
// Para2: 00=Stammdaten aus Kopf, sonst Anzahl Stammdaten (1..9)
|
|
//
|
|
//RE_VAL: Bit0=kein Datenlistenbereich, Bit1=Kopier-/SFC-Fehler, Bit2=Listenende,
|
|
// Bit3=falscher Parameter, Bit4=undef. Suchdaten, Bit5=undef. OutDaten,
|
|
// Bit6=Datensatz nicht vorhanden, Bit7=Daten vorhanden. Erfolg zusaetzlich via ENO/BR.
|
|
//
|
|
//ABWEICHUNGEN ZUM AWL-ORIGINAL:
|
|
// - SEARCHDATEN/OUTDATEN sind VARIANT statt POINTER (S7-1500/SCL).
|
|
// SEARCHDATEN muss mind. Stammdaten*2 Bytes referenzieren.
|
|
// OUTDATEN sollte exakt Datensatzlaenge*2 Bytes gross sein (groessere Ziele
|
|
// werden hinter dem Datensatz mit 0 aufgefuellt).
|
|
// - Die DB-Laengenpruefung des Such-/Out-DB (AWL NW5/NW8) entfaellt, da der
|
|
// Variant-Zugriff typsicher ist. Fehlerbit 5 (undef. OutDaten) wird nicht mehr erzeugt.
|
|
// - Der indirekte Aufruf UC FC[#Wandel_FC] ist als CASE ausgefuehrt
|
|
// (aktuell einziger Wandel-FC im Projekt: FC1000 "Wandel_FC_fuer_DB1000").
|
|
// - Position wird mit 0 initialisiert (AWL: undefiniert, wenn nicht gefunden).
|
|
VAR_INPUT
|
|
SSDB : Int; // Datenlisten-DB
|
|
SSDW : Int; // Datenlisten-1.DW (Byte-Offset des Kopfs)
|
|
PARA : Word; // Aufrufparameter (Auftrag / Anzahl Stammdaten)
|
|
SEARCHDATEN : Variant; // Such-Daten-Schnittstelle (Stammdaten Worte)
|
|
END_VAR
|
|
|
|
VAR_OUTPUT
|
|
RE_VAL : Byte; // Rueckmeldung (Fehler-/Statusbits)
|
|
Position : Int; // Daten stehen an angegebener Position in Datenliste
|
|
END_VAR
|
|
|
|
VAR_IN_OUT
|
|
OUTDATEN : Variant; // OutDaten-Schnittstelle (Datensatzlaenge Worte)
|
|
END_VAR
|
|
|
|
VAR_TEMP
|
|
Kopf : Byte; // Datenliste-Kennung (DA/DB)
|
|
Datensatzlaenge : Int; // Datensatzlaenge in Word (1..128)
|
|
Listenlaenge : Int; // Laenge der Datenliste (max. Anzahl Datensaetze)
|
|
Stammdaten : Int; // Stammdatenlaenge in Word (1..9)
|
|
IndDB : Word; // Indizierter DB (nur bei Stammdaten = 1 erlaubt !!!)
|
|
IndDB_Laenge : Int; // Laenge des indizierten DB in Eintraegen
|
|
IndDaten_FC : Int; // FC zum Wandeln der indizierten Daten
|
|
Suchzeiger : Int; // Speicherung des letzten Zugriffs / Suchzeiger (Byte-Adresse)
|
|
Para1 : Byte; // 1.Aufrufparameter
|
|
Para2 : Byte; // 2.Aufrufparameter
|
|
OffsetDaten_1 : Int; // Stammdaten beginnen ab hier (Byte-Offset)
|
|
SFC_RET_VAL : Int; // Rueckmeldung SFC-/Serialize-Aufruf
|
|
SFC_DB_LENGTH : Word; // Rueckmeldung TEST_DB-Aufruf
|
|
SFC_WRITE_PROT : Bool; // Rueckmeldung TEST_DB-Aufruf (letzter Aufruf!)
|
|
DB_Laenge : Int; // DB-Laenge nach BCD-Wandlung (wie AWL)
|
|
Datenlisten_Ende : Int; // Ende der Datenliste (Byte-Offset Endekennung)
|
|
Datenblock_inBytes : Int; // Datenblocklaenge in Bytes
|
|
Daten_1 : Word; // 1.Datenwort der Suchdaten
|
|
Daten_2 : DWord; // 1.+2.Datenwort der Suchdaten (fuer Wandel-FC)
|
|
Wandel_FC : Int; // Wandel-FC-Nummer
|
|
Suchstelle : Int; // Bei angegebenem Datensatz suchen (Position)
|
|
LoeschPos : Int; // Loesch-Position
|
|
Indok : Bool; // Indizierung moeglich
|
|
IndZeiger_ok : Bool; // Indizier-Zeiger angegeben
|
|
Weitersuchen : Bool; // Weitersuchen ist aktiv (Para1 F1/FF)
|
|
Offsetsuchen : Bool; // Offsetsuchen ist aktiv
|
|
Sortliste : Bool; // Sortliste wird durchsucht
|
|
tRE_VAL : Byte; // Rueckmeldung (Zwischenwert)
|
|
tVKE : Bool; // Ergebnis fuer ENO (BR im AWL)
|
|
tGefunden : Bool; // Vergleichs-/Suchergebnis
|
|
tDbList : DInt; // Datenlisten-DB-Nummer fuer PEEK/POKE
|
|
tDbInd : DInt; // Indizierter DB fuer PEEK/POKE
|
|
tIndex : Int; // Indexwert fuer indizierte Suche
|
|
IndByteOfs : Int; // Byte-Offset des Index-Eintrags im IndDB
|
|
tWort : Word; // Wort-Zwischenwert
|
|
tAnz : Int; // Anzahl-Zwischenwert
|
|
tAnzBytes : Int; // Anzahl zu verschiebender Bytes
|
|
tPos : DInt; // Serialize-/Deserialize-Position
|
|
i : Int; // Schleifenzaehler
|
|
tSuchPuffer : Array[0..257] of Byte; // Zwischenpuffer SEARCHDATEN
|
|
tRecPuffer : Array[0..257] of Byte; // Zwischenpuffer Datensatz -> OUTDATEN
|
|
END_VAR
|
|
|
|
BEGIN
|
|
#tRE_VAL := 16#00;
|
|
#Suchstelle := 0;
|
|
#Position := 0;
|
|
|
|
REGION NW1: Schnittstellen-DB sinnvoll ?
|
|
#tDbList := 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);
|
|
"BCD (4stellig)_to_INT"(BCD_Wert := #SFC_DB_LENGTH, Int_Wert => #DB_Laenge);
|
|
|
|
IF (#SFC_RET_VAL <> 0) OR #SFC_WRITE_PROT THEN // schreibgeschuetzt
|
|
GOTO mErr0; // kein Datenlisten-Bereich
|
|
END_IF;
|
|
END_REGION
|
|
|
|
REGION NW2: Datenlisten-Kopf holen (AWL: Quelle-Pointer + BLKMOV, 10 Worte)
|
|
IF #SSDW < 0 OR (#SSDW + 20) > #DB_Laenge THEN
|
|
GOTO mErr1; // Kopf liegt nicht im DB (AWL: SFC20-Fehler)
|
|
END_IF;
|
|
|
|
#Kopf := PEEK(area := 16#84, dbNumber := #tDbList, byteOffset := INT_TO_DINT(#SSDW));
|
|
#Datensatzlaenge := BYTE_TO_INT(PEEK(area := 16#84, dbNumber := #tDbList, byteOffset := INT_TO_DINT(#SSDW + 1)));
|
|
#Listenlaenge := WORD_TO_INT(PEEK_WORD(area := 16#84, dbNumber := #tDbList, byteOffset := INT_TO_DINT(#SSDW + 2)));
|
|
#Stammdaten := WORD_TO_INT(PEEK_WORD(area := 16#84, dbNumber := #tDbList, byteOffset := INT_TO_DINT(#SSDW + 4)));
|
|
#IndDB := PEEK_WORD(area := 16#84, dbNumber := #tDbList, byteOffset := INT_TO_DINT(#SSDW + 6));
|
|
#IndDB_Laenge := WORD_TO_INT(PEEK_WORD(area := 16#84, dbNumber := #tDbList, byteOffset := INT_TO_DINT(#SSDW + 8)));
|
|
#IndDaten_FC := WORD_TO_INT(PEEK_WORD(area := 16#84, dbNumber := #tDbList, byteOffset := INT_TO_DINT(#SSDW + 10)));
|
|
#Suchzeiger := WORD_TO_INT(PEEK_WORD(area := 16#84, dbNumber := #tDbList, byteOffset := INT_TO_DINT(#SSDW + 12)));
|
|
END_REGION
|
|
|
|
REGION NW3: Zeigerueberpruefung
|
|
#Sortliste := (#Kopf = 16#DB); // Sort-Datenlistenkennung ?
|
|
IF NOT #Sortliste AND (#Kopf <> 16#DA) THEN // Datenlistenkennung ?
|
|
GOTO mErr0; // kein Datenlistenbereich
|
|
END_IF;
|
|
|
|
IF (#Datensatzlaenge < 1) OR (#Datensatzlaenge > 128)
|
|
OR (#Listenlaenge < 1)
|
|
OR (#Stammdaten < 1) OR (#Stammdaten > 9)
|
|
OR (#Stammdaten > #Datensatzlaenge) THEN
|
|
GOTO mErr0; // kein Datenlistenbereich
|
|
END_IF;
|
|
|
|
#Datenlisten_Ende := #Listenlaenge * #Datensatzlaenge * 2 + 20 + #SSDW;
|
|
|
|
IF #Datenlisten_Ende > #DB_Laenge THEN // Datenlisten-DB ist zu kurz!
|
|
GOTO mErr0; // kein Datenlisten-Bereich
|
|
END_IF;
|
|
|
|
#tWort := PEEK_WORD(area := 16#84, dbNumber := #tDbList, byteOffset := INT_TO_DINT(#Datenlisten_Ende));
|
|
IF (#tWort <> 16#DAEE) AND (#tWort <> 16#DBEE) THEN // Endekennung ?
|
|
GOTO mErr0; // kein Datenlisten-Bereich
|
|
END_IF;
|
|
|
|
#Datenblock_inBytes := #Datensatzlaenge * 2;
|
|
END_REGION
|
|
|
|
REGION NW4: Auftrag kontrollieren
|
|
#Indok := FALSE;
|
|
#IndZeiger_ok := FALSE;
|
|
#Weitersuchen := FALSE;
|
|
#Offsetsuchen := FALSE;
|
|
#OffsetDaten_1 := 0; // Vorerst kein Offset
|
|
|
|
#Para1 := WORD_TO_BYTE(SHR(IN := #PARA, N := 8));
|
|
#Para2 := WORD_TO_BYTE(#PARA);
|
|
|
|
IF #Para1 = 16#00 THEN // Normale Suche
|
|
GOTO mW401;
|
|
END_IF;
|
|
|
|
IF #Para1 = 16#E1 THEN // Suchen + loeschen
|
|
IF #Sortliste THEN
|
|
GOTO mErr3; // Austragen aus Sortliste nicht erlaubt !
|
|
END_IF;
|
|
GOTO mW401;
|
|
END_IF;
|
|
|
|
IF #Para1 = 16#F1 THEN // 1.Datensatz holen
|
|
IF (#Para2 <> 16#00) OR #Sortliste THEN
|
|
GOTO mErr3; // Falscher Aufrufparameter
|
|
END_IF;
|
|
#Weitersuchen := TRUE;
|
|
#Suchzeiger := #SSDW + 20;
|
|
GOTO mNw08; // OutDaten ok ?
|
|
END_IF;
|
|
|
|
IF #Para1 = 16#FF THEN // Naechsten Datensatz holen
|
|
IF (#Para2 <> 16#00) OR #Sortliste THEN
|
|
GOTO mErr3; // Falscher Aufrufparameter
|
|
END_IF;
|
|
#Weitersuchen := TRUE;
|
|
#Suchzeiger := #Suchzeiger + #Datenblock_inBytes; // Naechsten Datensatz suchen
|
|
IF (#Datenblock_inBytes * #Listenlaenge + #SSDW + 20) > #Suchzeiger THEN
|
|
GOTO mNw08; // Noch nicht am Ende
|
|
END_IF;
|
|
GOTO mErr2; // Listenende erreicht
|
|
END_IF;
|
|
|
|
// Offset-Suche: Para1 = Offset des 1.Stammdatenworts (2..128)
|
|
IF (BYTE_TO_INT(#Para1) < 2)
|
|
OR (BYTE_TO_INT(#Para1) > 128)
|
|
OR (BYTE_TO_INT(#Para1) > #Datensatzlaenge) THEN
|
|
GOTO mErr3; // Falscher Aufrufparameter
|
|
END_IF;
|
|
#OffsetDaten_1 := (BYTE_TO_INT(#Para1) - 1) * 2; // Richtiger Offset der 1.Stammdaten
|
|
#Suchzeiger := 0; // Suche ab Anfang
|
|
#Offsetsuchen := TRUE;
|
|
|
|
mW401: IF #Para2 <> 16#00 THEN
|
|
#Stammdaten := BYTE_TO_INT(#Para2); // Anzahl der Stammdaten aus Aufruf
|
|
IF (#Stammdaten > #Datensatzlaenge)
|
|
OR (#Stammdaten < 1)
|
|
OR (#Stammdaten > 9) THEN
|
|
GOTO mErr3; // Falscher Aufrufparameter
|
|
END_IF;
|
|
END_IF;
|
|
|
|
IF #Offsetsuchen THEN
|
|
IF (BYTE_TO_INT(#Para1) - 1 + #Stammdaten) > #Datensatzlaenge THEN // Letzte Stammdaten zu gross ?
|
|
GOTO mErr3; // Falscher Aufrufparameter
|
|
END_IF;
|
|
END_IF;
|
|
END_REGION
|
|
|
|
REGION NW5: Such-Daten uebernehmen (AWL: Pointer-Parsing)
|
|
#Suchzeiger := 0;
|
|
|
|
#tPos := 0;
|
|
#SFC_RET_VAL := Serialize(SRC_VARIANT := #SEARCHDATEN, DEST_ARRAY := #tSuchPuffer, POS := #tPos);
|
|
IF (#SFC_RET_VAL <> 0) OR (#tPos < INT_TO_DINT(#Stammdaten * 2)) THEN
|
|
GOTO mErr4; // Undefinierte Suchdaten
|
|
END_IF;
|
|
|
|
#Daten_1 := SHL(IN := BYTE_TO_WORD(#tSuchPuffer[0]), N := 8) OR BYTE_TO_WORD(#tSuchPuffer[1]);
|
|
#Daten_2 := SHL(IN := BYTE_TO_DWORD(#tSuchPuffer[0]), N := 24)
|
|
OR SHL(IN := BYTE_TO_DWORD(#tSuchPuffer[1]), N := 16)
|
|
OR SHL(IN := BYTE_TO_DWORD(#tSuchPuffer[2]), N := 8)
|
|
OR BYTE_TO_DWORD(#tSuchPuffer[3]);
|
|
|
|
// Mindestens ein Suchwort <> 0 ?
|
|
#tGefunden := FALSE;
|
|
FOR #i := 0 TO #Stammdaten - 1 DO
|
|
IF (#tSuchPuffer[#i * 2] <> 16#00) OR (#tSuchPuffer[#i * 2 + 1] <> 16#00) THEN
|
|
#tGefunden := TRUE;
|
|
EXIT;
|
|
END_IF;
|
|
END_FOR;
|
|
IF NOT #tGefunden THEN
|
|
GOTO mErr4; // Undefinierte Stammdaten
|
|
END_IF;
|
|
END_REGION
|
|
|
|
REGION NW6: Indiziert suchen ?
|
|
IF (#IndDB <> 16#0000) AND NOT #Offsetsuchen AND NOT #Sortliste THEN
|
|
"TEST_DB_TO_ATTR_DB"(DB_Number := #IndDB,
|
|
RetVal => #SFC_RET_VAL,
|
|
DB_Length => #SFC_DB_LENGTH,
|
|
Write_Prot => #SFC_WRITE_PROT);
|
|
"BCD (4stellig)_to_INT"(BCD_Wert := #SFC_DB_LENGTH, Int_Wert => #DB_Laenge);
|
|
|
|
IF (#SFC_RET_VAL = 0) AND NOT #SFC_WRITE_PROT // Indizier-DB vorhanden
|
|
AND NOT (#IndDB_Laenge * 2 > #DB_Laenge) // Indizier-DB lang genug
|
|
AND (#Stammdaten < 3) THEN // nicht zu viele Stammdaten
|
|
#Wandel_FC := #IndDaten_FC;
|
|
IF #Wandel_FC > 0 THEN
|
|
"MW90" := #Daten_1; // Stammdaten (1.DW) uebergeben
|
|
"MD94" := #Daten_2; // Stammdaten (1.+2.DW) uebergeben
|
|
CASE #Wandel_FC OF // AWL: UC FC[#Wandel_FC]
|
|
1000:
|
|
"Wandel_FC_für_DB1000"();
|
|
ELSE
|
|
; // unbekannter Wandel-FC: MW92 bleibt unveraendert
|
|
END_CASE;
|
|
#tIndex := WORD_TO_INT("MW92"); // Rueckwert vom FC
|
|
ELSE
|
|
#tIndex := WORD_TO_INT(#Daten_1); // Stammdaten direkt als Index
|
|
END_IF;
|
|
|
|
IF (#tIndex >= 0) AND (#tIndex < #IndDB_Laenge) THEN // Zeiger im Ind.DB ?
|
|
#IndByteOfs := #tIndex * 2; // DB byteorientiert
|
|
#tDbInd := INT_TO_DINT(WORD_TO_INT(#IndDB));
|
|
#Suchzeiger := WORD_TO_INT(PEEK_WORD(area := 16#84, dbNumber := #tDbInd,
|
|
byteOffset := INT_TO_DINT(#IndByteOfs)));
|
|
#Indok := TRUE; // Indizierung moeglich
|
|
#IndZeiger_ok := TRUE; // Indizier-Zeiger angegeben
|
|
END_IF;
|
|
END_IF;
|
|
END_IF;
|
|
END_REGION
|
|
|
|
REGION NW7: Kontrolle auf gleiche Stammdaten (Suchschleife)
|
|
IF (#Suchzeiger = 0)
|
|
OR (((#Suchzeiger - 20) MOD #Datenblock_inBytes) <> 0) THEN // Suchzeiger nicht im Raster
|
|
// Suche bei 1.Datensatz beginnen (AWL: W700)
|
|
#Suchstelle := 1;
|
|
#IndZeiger_ok := FALSE;
|
|
#Suchzeiger := #SSDW + 20;
|
|
ELSE
|
|
#Suchstelle := 0; // Bei angegebener Stelle suchen
|
|
END_IF;
|
|
|
|
REPEAT
|
|
// Stammdaten vergleichen (AWL: W701/L700-Schleife)
|
|
#tGefunden := TRUE;
|
|
FOR #i := 0 TO #Stammdaten - 1 DO
|
|
#tWort := SHL(IN := BYTE_TO_WORD(#tSuchPuffer[#i * 2]), N := 8)
|
|
OR BYTE_TO_WORD(#tSuchPuffer[#i * 2 + 1]);
|
|
IF #tWort <> PEEK_WORD(area := 16#84, dbNumber := #tDbList,
|
|
byteOffset := INT_TO_DINT(#Suchzeiger + #OffsetDaten_1 + #i * 2)) THEN
|
|
#tGefunden := FALSE;
|
|
EXIT;
|
|
END_IF;
|
|
END_FOR;
|
|
|
|
IF #tGefunden THEN
|
|
#tRE_VAL := 16#80; // Daten sind vorhanden
|
|
GOTO mNw08; // Datensatz ist in Liste enthalten
|
|
END_IF;
|
|
|
|
// AWL: W703
|
|
IF #Suchstelle = 0 THEN
|
|
// Suche bei angegebener Stelle erfolglos: ab 1.Datensatz neu (AWL: W700)
|
|
#Suchstelle := 1;
|
|
#IndZeiger_ok := FALSE;
|
|
#Suchzeiger := #SSDW + 20;
|
|
ELSE
|
|
#Suchstelle := #Suchstelle + 1;
|
|
IF #Suchstelle > #Listenlaenge THEN // Alle Datensaetze durchsucht
|
|
GOTO mErr6; // Datensatz ist nicht vorhanden
|
|
END_IF;
|
|
#Suchzeiger := #Suchzeiger + #Datenblock_inBytes; // AWL: W705
|
|
END_IF;
|
|
UNTIL FALSE END_REPEAT;
|
|
END_REGION
|
|
|
|
REGION NW8+NW9: Datensatz an OUTDATEN uebergeben
|
|
mNw08: FILL_BLK(IN := BYTE#16#00, COUNT := 258, OUT => #tRecPuffer[0]);
|
|
|
|
FOR #i := 0 TO #Datensatzlaenge * 2 - 1 DO
|
|
#tRecPuffer[#i] := PEEK(area := 16#84, dbNumber := #tDbList,
|
|
byteOffset := INT_TO_DINT(#Suchzeiger + #i));
|
|
END_FOR;
|
|
|
|
#tPos := 0;
|
|
#SFC_RET_VAL := Deserialize(SRC_ARRAY := #tRecPuffer, DEST_VARIANT := #OUTDATEN, POS := #tPos);
|
|
IF #SFC_RET_VAL <> 0 THEN
|
|
GOTO mErr1; // Kopier-Fehler (AWL: SFC20-Aufruf mit Fehler)
|
|
END_IF;
|
|
|
|
IF NOT #SFC_WRITE_PROT THEN // Datenliste kann beschrieben werden
|
|
// Speicherung letzter Zugriff
|
|
POKE(area := 16#84, dbNumber := #tDbList, byteOffset := INT_TO_DINT(#SSDW + 12),
|
|
value := INT_TO_WORD(#Suchzeiger));
|
|
#Position := #Suchstelle; // Uebergabe nach aussen
|
|
END_IF;
|
|
END_REGION
|
|
|
|
REGION NW10+NW11: Daten aus Datenliste loeschen ?
|
|
IF (#Para1 = 16#E1) AND NOT #SFC_WRITE_PROT THEN // Daten loeschen ?
|
|
IF #Indok THEN
|
|
// NW11: Bei ind. Zugriff nur loeschen, nicht verschieben, keine Anzahl!
|
|
FOR #i := 0 TO #Datensatzlaenge - 1 DO
|
|
POKE(area := 16#84, dbNumber := #tDbList,
|
|
byteOffset := INT_TO_DINT(#Suchzeiger + #i * 2), value := WORD#16#0000);
|
|
END_FOR;
|
|
POKE(area := 16#84, dbNumber := #tDbList, byteOffset := INT_TO_DINT(#SSDW + 12),
|
|
value := WORD#16#0000); // letzter Zugriff loeschen
|
|
#Suchzeiger := 0;
|
|
#IndZeiger_ok := FALSE;
|
|
ELSE
|
|
// NW10: loeschen + nachfolgende Datensaetze vorschieben
|
|
#LoeschPos := (#Suchzeiger - 20 - #SSDW) / #Datenblock_inBytes + 1; // Stelle, die geloescht wird
|
|
IF #LoeschPos <> #Listenlaenge THEN // nicht der letzte Eintrag
|
|
// Daten verschieben (AWL: BLKMOV; hier bytewise vorwaerts = sicher bei Ueberlappung)
|
|
#tAnzBytes := (#Listenlaenge - #LoeschPos) * #Datenblock_inBytes;
|
|
FOR #i := 0 TO #tAnzBytes - 1 DO
|
|
POKE(area := 16#84, dbNumber := #tDbList,
|
|
byteOffset := INT_TO_DINT(#Suchzeiger + #i),
|
|
value := PEEK(area := 16#84, dbNumber := #tDbList,
|
|
byteOffset := INT_TO_DINT(#Suchzeiger + #Datenblock_inBytes + #i)));
|
|
END_FOR;
|
|
END_IF;
|
|
|
|
// Letzten Eintrag loeschen (AWL: Last)
|
|
FOR #i := 0 TO #Datensatzlaenge - 1 DO
|
|
POKE(area := 16#84, dbNumber := #tDbList,
|
|
byteOffset := INT_TO_DINT(#Datenlisten_Ende - #Datenblock_inBytes + #i * 2),
|
|
value := WORD#16#0000);
|
|
END_FOR;
|
|
|
|
// Speicherung letzter Zugriff loeschen
|
|
POKE(area := 16#84, dbNumber := #tDbList, byteOffset := INT_TO_DINT(#SSDW + 12),
|
|
value := WORD#16#0000);
|
|
#Suchzeiger := 0;
|
|
#IndZeiger_ok := FALSE;
|
|
|
|
// Anzahl Eintraege -1 (Minimum 0)
|
|
#tAnz := WORD_TO_INT(PEEK_WORD(area := 16#84, dbNumber := #tDbList,
|
|
byteOffset := INT_TO_DINT(#SSDW + 16))) - 1;
|
|
IF #tAnz < 0 THEN
|
|
#tAnz := 0; // Minimum uebergeben
|
|
END_IF;
|
|
POKE(area := 16#84, dbNumber := #tDbList, byteOffset := INT_TO_DINT(#SSDW + 16),
|
|
value := INT_TO_WORD(#tAnz));
|
|
END_IF;
|
|
END_IF;
|
|
END_REGION
|
|
|
|
REGION NW12: Weitersuchen aktiv ? Datensatz vorhanden oder 0 ?
|
|
IF #Weitersuchen THEN
|
|
#tGefunden := FALSE;
|
|
FOR #i := 0 TO #Datensatzlaenge - 1 DO
|
|
IF (#tRecPuffer[#i * 2] <> 16#00) OR (#tRecPuffer[#i * 2 + 1] <> 16#00) THEN
|
|
#tGefunden := TRUE; // Etwas angegeben
|
|
EXIT;
|
|
END_IF;
|
|
END_FOR;
|
|
IF #tGefunden THEN
|
|
#tRE_VAL := 16#80; // Daten sind vorhanden
|
|
ELSE
|
|
#tRE_VAL := 16#40; // Daten sind nicht vorhanden
|
|
END_IF;
|
|
GOTO mEnde;
|
|
END_IF;
|
|
END_REGION
|
|
|
|
REGION NW13: Indizierung ok ?
|
|
IF #Indok AND NOT #IndZeiger_ok THEN
|
|
// Index-Eintrag im indizierten DB aktualisieren
|
|
POKE(area := 16#84, dbNumber := #tDbInd, byteOffset := INT_TO_DINT(#IndByteOfs),
|
|
value := INT_TO_WORD(#Suchzeiger));
|
|
END_IF;
|
|
END_REGION
|
|
|
|
REGION NW14+NW15: Fehlerausgabe / RET_VAL
|
|
mEnde: #tVKE := TRUE; // VKE = 1 ohne Fehler !!!
|
|
GOTO mOk;
|
|
|
|
mErr0: #tRE_VAL := 16#01; // Kein Datenlistenbereich
|
|
GOTO mErrX;
|
|
mErr1: #tRE_VAL := 16#02; // Kopier-/SFC-Fehler
|
|
GOTO mErrX;
|
|
mErr2: #tRE_VAL := 16#04; // Listenende ist erreicht
|
|
GOTO mErrX;
|
|
mErr3: #tRE_VAL := 16#08; // Falscher Parameter bei Aufruf
|
|
GOTO mErrX;
|
|
mErr4: #tRE_VAL := 16#10; // Undefinierte Suchdaten
|
|
GOTO mErrX;
|
|
mErr6: #tRE_VAL := 16#40; // Datensatz nicht vorhanden
|
|
|
|
mErrX: #tVKE := FALSE; // VKE = 0 bei Fehler !!!
|
|
|
|
mOk: #RE_VAL := #tRE_VAL;
|
|
ENO := #tVKE; // AWL: SAVE (BR-Bit fuer JBI beim Aufrufer)
|
|
END_REGION
|
|
END_FUNCTION
|