SCL Baustein für azyklische Datenübertragung per RS-232

Draco Malfoy

Level-1
Beiträge
1.168
Reaktionspunkte
82
Zuviel Werbung?
-> Hier kostenlos registrieren
Guten Abend zusammen.

Gesucht wird eine Möglichkeit, serielle Kommunikation mit einem ET200Si Modul dergestalt zu bewerkstelligen, daß ein Paketversand mit definierten Wartezeiten zwischen den Zeichen möglich ist. Die Schnittstellen-Baugruppe hat die Bestellnummer 6ES7 138-4DF01-0AB0 und benutzt im Normalfall die Bausteine FB 2 S_SEND_SI und FB 3 S_RECV_SI.

Da in dem zugehörigen Siemens-Beispielprojekt für die serielle Kommunikation die gewünschte Funktionalität so nicht dargestellt ist, habe ich mal einen kleinen Baustein in SCL verfasst. Eins vorab: ich kenne mich in SCL kaum aus. Gibt es eine Hoffnung, daß dieser Code in Etwa funktionieren könnte ?

Dank allseits im Voraus!

Code:
FUNCTION_BLOCK "FB 23_ASCII-COMMUN"
TITLE = ASCIICOM
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : Malfoy
FAMILY : 'MDP-82'
NAME : ASCII
VERSION : 1.0

//Serielle Kommunikation über die RS-232 Schnittstelle mittels 6ES7 138-4DF01-0AB0 ET200Si Modul

   VAR_INPUT 
      Start_Initialisierung : Bool;
      FIRST_STATE : Bool;
   END_VAR

   VAR 
      Timer_WAITINGTIME {OriginalPartName := 'TON'; LibVersion := '1.0'} : TON;
      RECIVE_DATA : "S_RECV_SI";
      SEND_DATA : "S_SEND_SI";
      COUNTER_ZEICHEN_IM_BEFEHL : Int;
      COUNTER_BEFEHLE : Int;
   END_VAR

   VAR CONSTANT 
      DBB_OFFSET : Int := 1;
      DB_OFFSET : Int := 30;
      CARRIER_WAITING_TIME : Time := T#37mS;
   END_VAR


BEGIN
        IF #Start_Initialisierung AND NOT #FIRST_STATE THEN
            // -------------------------------------
            // SENDEN - FB 2_S_SEND_SI MULTIINSTANZ;
            // -------------------------------------
            // 
            #SEND_DATA.REQ := "SEND_ WORK_DB_SI_0".S_SEND_SI_REQ;
            #SEND_DATA.R := "SEND_ WORK_DB_SI_0".S_SEND_SI_R;
            #SEND_DATA.LADDR := "SEND_ WORK_DB_SI_0".S_SEND_SI_WORK_LADDR;
            #SEND_DATA.DB_NO := "SEND_ WORK_DB_SI_0".S_SEND_SI_WORK_DB_NO;
            #SEND_DATA.DBB_NO := "SEND_ WORK_DB_SI_0".S_SEND_SI_WORK_DBB_NO;
            #SEND_DATA.LEN := "SEND_ WORK_DB_SI_0".S_SEND_SI_WORK_LEN;
            #SEND_DATA.DONE := "SEND_ WORK_DB_SI_0".S_SEND_SI_DONE;
            #SEND_DATA.ERROR := "SEND_ WORK_DB_SI_0".S_SEND_SI_ERROR;
            #SEND_DATA.STATUS := "SEND_ WORK_DB_SI_0".S_SEND_SI_WORK_STAT;
            #SEND_DATA.COM_RST := "SEND_ WORK_DB_SI_0".S_SEND_SI_COM_RST;
        END_IF;
        //**************************PERMANENTE ANWEISUNGEN***************************************//
        //***************************************************************************************//
        //********BEFEHLE WERDEN IM SOURCE DATEN_DB in Blöcken mit je 30 Zeichen abgelegt *******//
        //
        // -----------------------------------------------------------------------------------------------------------------------------
        // Ein Befehl erhält die Array-Adresse: Grundadresse (bsplsw. DB20.DBB10) + Offset von 30 Zeichen, wobei nicht immer alle 30
        // Zeichen gesendet werden müssen, sondern nur die Länge, die aktuell in dem Counter ZEICHEN anhängig von dem Stand des
        // Counters BEFEHLE abgelegt ist. Anm.: Korrekte Werte eintragen / überprüfen 
        // -----------------------------------------------------------------------------------------------------------------------------
        //
        
        #COUNTER_BEFEHLE := 17;
        
        IF #FIRST_STATE AND NOT #Start_Initialisierung THEN
            WHILE (#COUNTER_BEFEHLE <> 0) DO
                 //
                 //------------------------------------------------
                 //KORREKTE ZEICHENLÄNGE DEN BEFEHLEN ZUORDNEN:
                 // -----------------------------------------------
                 // 
                CASE #COUNTER_BEFEHLE OF
                    0: #COUNTER_ZEICHEN_IM_BEFEHL := 18;    // Zeichenlänge des ersten Befehls;
                    1: #COUNTER_ZEICHEN_IM_BEFEHL := 20;    // Zeichenlänge des zweiten Befehls;
                    2..8: #COUNTER_ZEICHEN_IM_BEFEHL := 18; // Zeichenlänge der Befehle 3 bis 9;
                    9:  #COUNTER_ZEICHEN_IM_BEFEHL := 22;   // Zeichenlänge des 10. Befehls;
                    ELSE  
                        #COUNTER_ZEICHEN_IM_BEFEHL := 18;   // Darüber hinaus;
                END_CASE;
                //
                // ------------------------------------------------------------
                // TIMER FÜR DIE NÄCHSTE ÜBERTRAGUNG SETZEN, WENN ABGELAUFEN:
                // ------------------------------------------------------------
                // 
                IF (#Timer_WAITINGTIME.IN <> true) THEN
                    #Timer_WAITINGTIME.IN := true;
                    #Timer_WAITINGTIME.PT := #CARRIER_WAITING_TIME;
                END_IF;
                //
                // -----------------------------------------------------------------------------
                // DATENLÄNGE ABHÄNGIG VOM COUNTER -> UNNÖTIG DA ZEICHENWEISE GESENDET WIRD ??
                // -----------------------------------------------------------------------------
                // 
                IF (#COUNTER_ZEICHEN_IM_BEFEHL <> 0) THEN
                    #SEND_DATA.LEN := 1;
                END_IF;
                //
                // -----------------------------------------------------------------
                // DATEN SENDEN PER SCHLEIFE mit TIMER (jeweils 1 Zeichen lang):
                // -----------------------------------------------------------------
                // 
                WHILE (#COUNTER_ZEICHEN_IM_BEFEHL <> 0) DO
                    IF NOT #SEND_DATA.ERROR AND #SEND_DATA.DONE AND #Timer_WAITINGTIME.Q THEN
                        
                        IF NOT #SEND_DATA.REQ THEN
                            #SEND_DATA.REQ := true;
                        END_IF;
                        
                        #COUNTER_ZEICHEN_IM_BEFEHL := #COUNTER_ZEICHEN_IM_BEFEHL - 1; // Schleifenzähler dekrementieren
                        #SEND_DATA.DBB_NO := #SEND_DATA.DBB_NO + #DBB_OFFSET; //Offset für den nächsten Zugriff generieren
                        #Timer_WAITINGTIME.IN := false; // Unterbrechung des Timers On Delay setzen
                        
                    END_IF;
                END_WHILE;
                
                #SEND_DATA.DBB_NO := #SEND_DATA.DBB_NO + #DB_OFFSET; // Offset für den folgenden Befehl generieren
                #COUNTER_BEFEHLE := #COUNTER_BEFEHLE - 1; //Schleifenzähler dekrementieren
            END_WHILE;
        END_IF;
    
        
        
END_FUNCTION_BLOCK
 
Zuletzt bearbeitet:
Zurück
Oben