FUNCTION_BLOCK FB50
(*Variablendeklaration
***************************************************************************************************)
VAR_INPUT //Eingangsvariablen
IN_suchen:BOOL;
IN_DBNR:INT;
IN_DBM:INT;
IN_Zyklen:INT;
IN_Loop:INT;
IN_DSlen:INT;
IN_Stringlaenge:INT;
IN_Artikel:STRING;
END_VAR
VAR_OUTPUT //Ausgangsvariablen
OUT_busy:BOOL;
OUT_gefunden:BOOL;
OUT_DB:INT;
OUT_DBB:INT;
END_VAR
VAR //Statische Variablen
STAT_suchen:BOOL;
STAT_busy:BOOL;
STAT_gefunden:BOOL;;
STAT_DBB:INT;
STAT_Loop:INT;
STAT_Zyklus:INT;
STAT_DSNR:INT;
STAT_DBNR:INT;
STAT_DBM:INT;
STAT_For_Min:INT;
STAT_For_Max:INT;
STAT_Zyklen:INT;
STAT_LoopSoll:INT;
STAT_DSlen:INT;
STAT_Stringlaenge:INT;
STAT_DB_Artikel:STRING;
END_VAR
VAR_TEMP //Temoräre Variablen
TEMP_Source : ANY; //Any Quellzeiger
VON AT TEMP_Source: STRUCT //AT-Befehl: Die einzelnen Bestandteile der vorhergehenden Variablen werden in einer Struktur aufgeschlüsselt
ID : WORD;
NBR : INT;
DBN : INT;
PTR : DWORD;
END_STRUCT;
TEMP_DESTIN : ANY; //Any Zielzeiger
NACH AT TEMP_DESTIN: STRUCT //AT-Befehl: Die einzelnen Bestandteile der vorhergehenden Variablen werden in einer Struktur aufgeschlüsselt
ID : WORD;
NBR : INT;
DBN : INT;
PTR : DWORD;
END_STRUCT;
TEMP_DB_Artikel:STRING; //Vergleichsstring
Aufbau AT TEMP_DB_Artikel: STRUCT
MAXlen:BYTE;
ISTlen:BYTE;
Zeichen:ARRAY[1..254] OF BYTE;
END_STRUCT;
TEMP_SFC_Err:INT;
TEMP_Faktor:DINT;
TEMP_Produkt:DINT;
END_VAR
(*Initialisierung
****************************************************************************************************)
STAT_Zyklen := IN_Zyklen; //Eingangswerte an statische Variablen übergeben
STAT_LoopSoll := IN_Loop;
STAT_Stringlaenge := IN_Stringlaenge;
STAT_DSlen := IN_DSlen;
STAT_DBM := IN_DBM;
(*Programmcode
****************************************************************************************************)
IF (STAT_busy = false) AND (IN_suchen <> STAT_suchen) AND (IN_suchen = true) THEN //Suche Starten wenn nicht aktiv und Startflanke
STAT_busy := true;
STAT_gefunden := false; //Suche aktiv setzen
STAT_Zyklus := 0; //Zyklusanzahl initialisieren
STAT_DBNR := IN_DBNR;
END_IF;
IF (STAT_busy = true) AND (STAT_Zyklus < STAT_Zyklen) AND (STAT_DBNR < (IN_DBNR + STAT_DBM))THEN //Bedingung: Suchen gestartet und Anzahl Zyklen und DB´s < SOLL
STAT_For_Min := STAT_Zyklus * STAT_LoopSoll; //FOR-Schleife Minimum = Suchzyklus * Anzahl der Durchläufe pro Zyklus
STAT_For_Max := STAT_For_Min + STAT_LoopSoll; //FOR-Schleife Maximum = Minimum + Anzahl der Durchläufe pro Zyklus
FOR STAT_Loop := STAT_For_Min TO STAT_For_Max DO //FOR-Schleife von Minimum bis Maximum. STAT_Loop: Wert des aktuellen Durchlaufs
STAT_DSNR := STAT_Zyklus + STAT_Loop; //Die aktuelle Datensatznummer ergibt sich aus der Anzahl der Zyklen und Loops
TEMP_Faktor := 8 * STAT_DSlen; //Faktor: 8 (für Bit) * Datensatzlänge in BYTE
TEMP_Produkt := STAT_DSNR * TEMP_Faktor; //TEMP_Produkt: Offset des aktuellen Datensatzes
VON.ID := w#16#1002; //10: "Siemens"; 02: Datentyp BYTE
VON.NBR := (STAT_Stringlaenge + 2); //Anzahl der zu Übertragenden Bytes
VON.DBN := STAT_DBNR; //aktuelle Datenbausteinnummer
VON.PTR := DINT_TO_DWORD(TEMP_Produkt) OR 16#8400_0000; //keine Berechnung für DINT_TO_DWORD, deshalb Berechnung vorher 84: Speicherbereich Datenbaustein
NACH.ID := w#16#1002; //10: "Siemens"; 02: Datentyp BYTE
NACH.NBR := (STAT_Stringlaenge + 2); //Anzahl der zu Übertragenden Bytes
NACH.DBN := 0; //"0", da Instanzdatenbaustein
NACH.PTR := INT_TO_WORD(302 * 8) OR 16#8500_0000; //Achtung: Offset abhängig von IDB-Aufbau; 85: Speicherbereich Instanzdatenbaustein
TEMP_SFC_Err := BLKMOV(SRCBLK := TEMP_Source, DSTBLK := TEMP_DESTIN); //SFC20 "Blockmove" Quellzeiger in Zielzeiger. Rückgabewert: Bearbeitungsfehler
TEMP_DB_Artikel := STAT_DB_Artikel; //von Any "NACH" wird auf STAT_DB_Artikel gezeigt und dieser dann in TEMP_DB_Artikel geschrieben
Aufbau.ISTlen := INT_TO_BYTE(STAT_Stringlaenge); //Istlänge des Strings wird beschrieben damit der Vergleich korrekt durchgeführt wird.
IF IN_Artikel = TEMP_DB_Artikel THEN //Stringvergleich (benötigt FC10 "EQ_STRING" Bibliothek: IEC)
STAT_gefunden := true; //Bei "TRUE": -Artikel gefunden
STAT_busy := false; // -Suche beenden
OUT_DBB := STAT_DSlen*STAT_DSNR; // -Offsetwert des Speicherbereichs im DB
OUT_DB := STAT_DBNR; // -Datenbausteinnummer
EXIT; // -Schleife beenden
ELSE
STAT_gefunden := false; //Bei "FALSE": -Artikel nicht gefunden
END_IF;
END_FOR;
STAT_Zyklus := STAT_Zyklus + 1; //Zyklus durchlaufen: 1 Zyklus addieren
ELSE
STAT_busy := false; //Suche beenden
END_IF;
IF STAT_Zyklus >= STAT_Zyklen THEN //Alle Datensätze dieses DB´s geprüft
STAT_Zyklus := 0; //Zykluszähler resetten
STAT_DBNR := STAT_DBNR + 1; //DB durchlaufen: 1 Db addieren
END_IF;
STAT_suchen := IN_suchen; //Flankenmerker zum Suchstart neu beschreiben
(*Ausgaben
***********************************************************************************************)
OUT_busy := STAT_busy; //Ausgang suche läuft
OUT_gefunden := STAT_gefunden; //Ausgang STRING gefunden
END_FUNCTION_BLOCK