FUNCTION "DatenIn" : Void TITLE = Datenlisten-Modul { S7_Optimized_Access := 'FALSE' } AUTHOR : IBAE FAMILY : DLISTE NAME : DatenIn VERSION : 0.1 //COPYRIGHT by Ingenieurbüro A.Emmert //Ortsstr.33, D-869925 Fuchstal (Germany) //Tel.: 0049(0)8243-1254 //Version: P&O / 10.2024 //Version: ILS2100 / 06.11.2009 // //Datenblock in Datenliste eintragen //SSDB: Datenlisten-DB //SSDW: Datenlisten-1.DW //INDATEN: Pointer, wo einzutragende Daten stehen (P#DB1.DBX0.0, P#M220.0) //RE_VAL: Rückmeldungen: // Bit0: Kein Datenlistenbereich / falscher Kopfinhalt / Endekennung // Bit1: SFC20-Aufruf mit Fehler // Bit2: Liste ist voll // Bit3: Frei // Bit4: Undefinierte Indaten // Bit5: Frei // Bit6: Daten wurden überschrieben // Bit7: Eintrag ist richtig erfolgt // VAR_INPUT SSDB : Int; // Datenlisten-DB SSDW : Int; // Datenlisten-1.DW INDATEN : Pointer; // InDaten-Schnittstelle END_VAR VAR_OUTPUT RE_VAL : Byte; END_VAR VAR_TEMP Quelle : Any; // Zeiger, wo Rein-Daten sind Ziel : Any; // Zeiger, FIFO-Stelle Kopf : Byte; // Datenliste-Kennnung (DA) Datensatzlaenge : Byte; // Datensatzlänge in Word (01 - F0) F0=128 Listenlaenge : Int; // Länge der Datenliste (maximale Anzahl der Datensätze) Stammdaten : Int; // Stammdatenlänge in Word (1 - 9) IndDB : Word; // Indizierter DB (nur bei Stammdaten = 1 erlaubt !!!) IndDB_Laenge : Int; // Länge des indizierten DB in Einträge (nur bei Stammdaten = 1 erlaubt !!!) IndDaten_FC : Int; // FC zum Wandeln der indizierte Daten (nur bei Stammdaten = 1 erlaubt !!!) Schreibzeiger : Int; // Speicherung des letzten Zugriffs / Schreibzeiger Belegt14 : Int; // reserviert von Sort-Datenliste AnzahlEintraege : Int; // Anzahl der eingetragenen Datensätze (nicht bei ind.Zugriff!) Reserve18 : Int; // Reserve DBDatenliste : Word; // Datenlisten-DB SFC_RET_VAL : Int; // Rückmeldung SFC-Aufruf SFC_DB_LENGTH : Word; // Rückmeldung SFC-Aufruf Datenlisten_Ende : Word; // Ende der Datenliste AR2_Speicher : DWord; // Adress-Register 2 zwischenspeichern Schleife : Word; // Loopzähler DBInDaten : Word; // Indaten-DB, falls angegeben InDaten_Pointer : DWord; // In-Daten-Pointer: Kennung, Adresse InDaten_Startpunkt : Word; // In-Daten-Startpunkt: Adresse IndPointer : DWord; // Zeiger für IndDB Daten_1 : Word; // 1.Datenwort der Indaten Daten_2 : DWord; // 1+2.Datenwort der Indaten (falls ind.Suchen mit Stammdaten 2) LeerZeiger : Word; // Zeiger für Leerzelle Datenblock_inBytes : Word; // Datenblocklänge in Bytes Suchstelle : Word; // Bei angegebenen Datensatz suchen SFC_WRITE_PROT : Bool; // Rückmeldung SFC-Aufruf Indok : Bool; // Indizierung möglich IndZeiger_ok : Bool; // Indizier-Zeiger angegeben Sortliste : Bool; // Sortliste wird durchsucht tRE_VAL : Byte; // Rückmeldung AR1Zeiger : DWord; // Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes) DB_Länge : Int; Wandel_FC : Word; // Wandel-FC END_VAR BEGIN NETWORK TITLE = Schnittstellen-DB sinnvoll ? TAR2; T #AR2_Speicher;//AR2 zwischenspeichern L #SSDB; T #DBDatenliste; CALL "TEST_DB_TO_ATTR_DB" ( DB_Number := #DBDatenliste , RetVal := #SFC_RET_VAL , DB_Length := #SFC_DB_LENGTH , Write_Prot := #SFC_WRITE_PROT ); CALL "BCD (4stellig)_to_INT" ( BCD_Wert := #SFC_DB_LENGTH , Int_Wert := #DB_Länge ); L #SFC_RET_VAL; L 2#0000_0000_0000_0000; <>I; O #SFC_WRITE_PROT; SPB Err0;//kein Datenlisten-Bereich NETWORK TITLE = Datenlistekopf holen //Quelle-Pointer erzeugen: L 16#1004;//Kennung 10 + Word=04 T %LW0;//Any-Kennung, Datentyp L 16#000A;//10 Dw´s holen T %LW2;//Wiederholungen L #SSDB; T %LW4;//DB_Nummer L #SSDW;//Adresse SLD 3; L 16#8400_0000;//Kennung: Daten OD; T %LD6;//Kennung, Adresse CALL BLKMOV//1.-10.DW Datenliste holen {blk_type := 'Variant'} ( SRCBLK := #Quelle , RET_VAL := #SFC_RET_VAL , DSTBLK := P#L20.0 WORD 10 ); L #SFC_RET_VAL; L 2#0000_0000_0000_0000; <>I; SPB Err1; NETWORK TITLE = Zeigerüberprüfung L #Kopf;//Datenliste-Kopf L 16#DB;//= Sort-Datenlistekennung ? ==I;//Ja ! = #Sortliste;//Sortliste wird durchsucht SPB w030; TAK; L 16#DA;//= Datenlistekennung ? <>I;//Nein ! SPB Err0;//kein Datenlistebereich w030: L 1; L #Datensatzlaenge;//Datenblocklänge >I; SPB Err0;//kein Datenlistebereich L 128; >I; SPB Err0;//kein Datenlistebereich L 1; L #Listenlaenge;//Max.Anzahl von Datenblöcken >I; SPB Err0;//kein Datenlistebereich L 1; L #Stammdaten;//Anzahl der Stammdaten >I; SPB Err0;//kein Datenlistebereich L 9; >I; SPB Err0;//kein Datenlistebereich L #Stammdaten;//Anzahl der Stammdaten L #Datensatzlaenge;//Datenblocklänge >I; SPB Err0;//kein Datenlistebereich L #Listenlaenge;//Länge der Datenliste L #Datensatzlaenge;//Datenblocklänge *I; L 2;//DB byteorientiert *I; + 20;//Speichern ab 10.DW L #SSDW; +I; T #Datenlisten_Ende; ITD; SLD 3; T #AR1Zeiger;///Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes) AUF DB[ #DBDatenliste]; L #Datenlisten_Ende; L #DB_Länge; >I ;//Datenlisten-DB ist zu kurz! SPB Err0;//kein Datenlisten-Bereich L DBW[ #AR1Zeiger]; L 16#DAEE ;//Datenliste-Endekennung ? <>I;//Nein ! U(; TAK; L 16#DBEE;//Sort-Datenliste-Endekennung ? <>I;//Nein ! ); SPB Err0;//kein Datenlisten-Bereich L #Datensatzlaenge;//Datenblocklänge L 2; *I; T #Datenblock_inBytes;//Datenblocklänge in Bytes NETWORK TITLE = Indaten definiert ? //In-DATEN-Pointer übernehmen: L P##INDATEN; LAR2; L W[ AR2, P#0.0]; T #DBInDaten;//Indaten-DB L #DBInDaten;//Indaten-DB L 0;//Angegeben ? ==I;//Nein SPB W401; CALL "TEST_DB_TO_ATTR_DB" ( DB_Number := #DBInDaten , RetVal := #SFC_RET_VAL , DB_Length := #SFC_DB_LENGTH , Write_Prot := #SFC_WRITE_PROT ); CALL "BCD (4stellig)_to_INT" ( BCD_Wert := #SFC_DB_LENGTH , Int_Wert := #DB_Länge ); L #SFC_RET_VAL; L 2#0000_0000_0000_0000;//Fehler vorhanden ? <>I;//Ja ! SPB Err4;//Undefinierte Indaten L D[ AR2, P#2.0];//Kennung, Adresse L 16#00FF_FFFF;//Ohne Kennung UW; SRW 3;//Ohne Bit T #InDaten_Startpunkt; L #Datensatzlaenge;//Datenblocklänge L 2;//DB byteorientiert *I; L #InDaten_Startpunkt; +I; L #DB_Länge; >I;//Indaten-DB ist zu kurz SPB Err4;//Undefinierte Indaten W401: L D[ AR2, P#2.0];//Kennung, Adresse T #InDaten_Pointer; LAR2; L #DBInDaten;//Indaten-DB L 0;//Angegeben ? ==I;//Nein SPB W402; AUF DB[ #DBInDaten]; W402: L W[ AR2, P#0.0];//Indaten überprüfen T #Daten_1;//1.Indaten speichern L D[ AR2, P#0.0] ;//Suchdaten überprüfen T #Daten_2 ;//1.Suchdaten speichern L #Stammdaten; L400: T #Schleife; L #DBInDaten;//Indaten-DB L 0;//Angegeben ? ==I;//Nein SPB W403; AUF DB[ #DBInDaten]; W403: L W[ AR2, P#0.0];//Indaten überprüfen L 0;//Etwas angegeben ? <>I;//Ja ! SPB Nw05;//Weiter +AR2 P#2.0; L #Schleife; LOOP L400; SPA Err4;//Undefinierte Indaten NETWORK TITLE = Indiziert speichern ? Nw05: SET; R #Indok;//Indizierung möglich R #IndZeiger_ok;//Indizier-Zeiger angegeben L #IndDB;//Indizierter DB L 0;//Angegeben ? ==I;//Nein ! O #Sortliste;//Sortliste wird durchsucht SPB Nw06; CALL "TEST_DB_TO_ATTR_DB" ( DB_Number := #IndDB , RetVal := #SFC_RET_VAL , DB_Length := #SFC_DB_LENGTH , Write_Prot := #SFC_WRITE_PROT ); CALL "BCD (4stellig)_to_INT" ( BCD_Wert := #SFC_DB_LENGTH , Int_Wert := #DB_Länge ); L #SFC_RET_VAL; L 2#0000_0000_0000_0000; <>I; O #SFC_WRITE_PROT; SPB Nw06;//kein Indizier-DB vorhanden L #IndDB_Laenge;//Länge des Indizierten DB überschritten ? L 2;//DB byteorientiert *I; L #DB_Länge; >I ;//Indizier-DB ist zu kurz SPB Nw06;//Zeiger ausserhalb Ind.DB L #Stammdaten;//Stammdaten L 3 ;//zu viele Stammdaten ? >=I ;//Ja ! SPB Nw06 ;//ohne Indizierung weiter L #IndDaten_FC;//Offset zum Abziehen T #Wandel_FC; L 0;//Parameter vorhanden ? <=I;//Nein SPB NoFC;//Bei diesem Schritt weiter L #Daten_1 ;//Stammdaten (1.DW) T "MW90";//übergeben L #Daten_2 ;//Stammdaten (2.DW) T "MD94" ;//übergeben UC FC[ #Wandel_FC];//Beeinflussung der Weiterfahrt L "MW92";//Rückwert von FC SPA Ret; NoFC: L #Daten_1;//Stammdaten Ret: T #IndPointer;//Stelle, wo Zeiger hinterlegt ist L 0; I;//Schreibzeiger nicht im Raster ! SPB W600;//Suche bei 1.Datensatz beginnen L 0;//Bei angegebener Stelle suchen T #Suchstelle;//Such bei X-ten Datensatz SPA W601; W600: L 1;//Suche bei 1.Datensatz beginnen T #Suchstelle;//Such bei X-ten Datensatz SET; R #IndZeiger_ok;//Indizier-Zeiger angegeben L #SSDW; + 20;//Offset für 1.Daten T #Schreibzeiger;//Schreibzeiger W601: L #Schreibzeiger;//Schreibzeiger ITD; SLD 3; T #AR1Zeiger;///Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes) L #InDaten_Pointer; LAR2; L #Stammdaten;//Anzahl der Stammdaten L600: T #Schleife; L #DBInDaten;//Indaten-DB L 0;//Angegeben ? ==I;//Nein SPB W602; AUF DB[ #DBInDaten]; W602: L W[ AR2, P#0.0];//Indaten überprüfen mit AUF DB[ #DBDatenliste]; L DBW[ #AR1Zeiger] ;//Datenliste-Daten lesen <>I ;//nicht identisch ! SPB W603; L #AR1Zeiger; SRD 3; L DINT#2; +D; SLD 3; T #AR1Zeiger; +AR2 P#2.0; L #Schleife; LOOP L600; L 2#0000_0000_1100_0000;//Daten werden gespeichert + überschrieben T #tRE_VAL;//Ok-Status SPA Nw07;//Datensatz ist in Liste enthalten W603: L 0;//Suche bei 1.Datensatz begonnen L #Suchstelle;//Such bei X-ten Datensatz ==I;//Nein ! SPB W600; L #LeerZeiger;//Zeiger Leerzelle L 0;//Gespeichert ? <>I;//Ja ! SPB W604; L #Schreibzeiger;//Schreibzeiger ITD; SLD 3; T #AR1Zeiger;///Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes) L #Datensatzlaenge; L601: T #Schleife; L DBW[ #AR1Zeiger] ;//Daten lesen L 0;//Leerzelle ? <>I;//Nein ! SPB W604; L #AR1Zeiger; SRD 3; L DINT#2; +D; SLD 3; T #AR1Zeiger; L #Schleife; LOOP L601; L #Schreibzeiger;//Schreibzeiger T #LeerZeiger;//Zeiger Leerzelle W604: L #Suchstelle;//Such bei X-ten Datensatz + 1; T #Suchstelle;//Such bei X-ten Datensatz L #Listenlaenge;//Anzahl aller Daten in Datenliste <=I;//Alle Datensätze sind durchsucht SPB W605;//Nein ! L 0;//Gefunden ? L #LeerZeiger;//Zeiger Leerzelle ==I;//Nein ! SPB Err2;//Datenliste ist voll T #Schreibzeiger;//Schreibzeiger L 2#0000_0000_1000_0000;//Daten werden gespeichert T #tRE_VAL;//Ok-Status SPA Nw07; W605: L #Datenblock_inBytes;//Datenblocklänge in bytes L #Schreibzeiger;//Schreibzeiger +I; T #Schreibzeiger;//Schreibzeiger SPA W601; NETWORK TITLE = Daten in Datenliste schreiben //Quelle-Pointer erzeugen: Nw07: L 16#1004;//Kennung 10 + Word=04 T %LW0; T %LW10;//Any-Kennung, Datentyp L #Datensatzlaenge;//Datenwords speichern T %LW2; T %LW12;//Wiederholungen //DATEN-Pointer übernehmen: L #DBInDaten; T %LW4;//DB_Nummer L #InDaten_Pointer; T %LD6;//Kennung, Adresse //Ziel-Pointer erzeugen: //Kennung + Datenbytes s.o. L #SSDB; T %LW14;//DB_Nummer L #Schreibzeiger;//Adresse SLD 3; L 16#8400_0000;//Kennung: Daten OD; T %LD16;//Kennung, Adresse CALL BLKMOV//Datenliste-Daten speichern {blk_type := 'Variant'} ( SRCBLK := #Quelle , RET_VAL := #SFC_RET_VAL , DSTBLK := #Ziel ); L #SFC_RET_VAL; L 2#0000_0000_0000_0000; <>I; SPB Err1; U #Sortliste;//Sortliste wird durchsucht SPB Nw8; L #SSDW; + 12; ITD; SLD 3; T #AR1Zeiger;///Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes) L #Schreibzeiger;//Schreibzeiger AUF DB[ #DBDatenliste]; T DBW[ #AR1Zeiger] ;//Speicherung letzter Zugriff L #tRE_VAL ;//Ok-Status L 2#0000_0000_1100_0000;//Daten werden gespeichert + überschrieben ? ==I;//Ja ! O #Indok ;//Indizierung möglich ((Dann nicht!) SPB Nw8 ;//Kein Neueintrag ! L #SSDW; + 16 ;//Offset Anzahl Einträge ITD; SLD 3; T #AR1Zeiger;///Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes) AUF DB[ #DBDatenliste]; L DBW[ #AR1Zeiger];//Anzahl der Einträge + 1;//Einträge +1 T DBW[ #AR1Zeiger];//Anzahl der Einträge NETWORK TITLE = Indizierung ok ? Nw8: UN #Indok;//Indizierung möglich O #IndZeiger_ok;//Indizier-Zeiger angegeben SPB Ende; AUF DB[ #IndDB];//Indizierter DB L #Schreibzeiger;//Schreibzeiger T DBW[ #IndPointer]; AUF DB[ #DBDatenliste];//Datenliste DB NETWORK TITLE = Fehlerausgabe / RET_VAL Ende: SET;//VKE = 1 ohne Fehler !!! L #tRE_VAL;//Ok-Status SPA Ok; Err0: L 2#0000_0000_0000_0001;//Kein Datenlistebereich SPA Err; Err1: L 2#0000_0000_0000_0010;//SFC20-Aufruf mit Fehler SPA Err; Err2: L 2#0000_0000_0000_0100;//Datenliste ist voll SPA Err; Err4: L 2#0000_0000_0001_0000;//Undefinierte Indaten Err: CLR;//VKE = 0 bei Fehler !!! Ok: T #tRE_VAL; SAVE;//VKE in BIE-Bit speichern L #AR2_Speicher;//AR2 zurückspeichern LAR2; NETWORK TITLE = Ausgangsvariablen schreiben L #tRE_VAL; T #RE_VAL; END_FUNCTION