Quantcast
Channel: SPS-Forum - Automatisierung und Elektrotechnik
Viewing all articles
Browse latest Browse all 46421

TIA SPS-Forum gemeinschaftsprojekt? DB im Ladespeicher sichern um Reinit zu verhindern

$
0
0
Hi zusammen

Viele hier nerven sich ja bestimmt auch über die unmotivierten Reinits von TIA wenn man das Programm in die Steuerung läd.
ich dachte mir, vielleicht besteht ja interesse gemeinsam an einem guten Baustein zu schreiben der uns einen ArbeitsspeicherDB in einen LadespeicherDB auf der Memorycard sichert und automatisch wiederherstellt.

Ich hab da mal was angefangen das grundsätzlich auch schon funktioniert. Aber er hat noch keine richtige Fehlerbehandlung und bestimmt einiges an Verbesserungspotential. Besteht interesse darin diesen Baustein offen weiterzuentwickeln und zu verbessern. Er soll aber weiterhin frei zugänglich bleiben (ggf erlauben das ja nicht alle Arbeitgeber mit Werksentwicklungslizenzen)

Hier was ich schon habe:
Code:

FUNCTION_BLOCK "SaveDatablock"
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : VoR
VERSION : 0.1
//Baustein soll einen kompletten DB im Ladespeicher sichern. Um TIA Reinitialisationen zu begrenzen.
//Der zu sichernde DB darf nicht optimiert sein.
//Die Sicherung muss durch SaveDB getriggert. SaveDB wird vom Baustein zurückgesetzt.
  VAR_INPUT
      DB_TO_SAVE : Any;  // Welcher DB soll gesichert werden
      DB_NR_Loadmem { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : UInt := 60000;  // DBNR_Ab 60000 im Ladespeicher
  END_VAR


  VAR_IN_OUT
      SaveDB : Bool;
      RecoverDB : Bool;
  END_VAR


  VAR
      DeleteDB : Bool;
      CreateDB : Bool;
      DelBusy : Bool;
      Attrib : Byte;
      Attr_DB_Lenght : UDInt;
      Create_DB_Busy : Bool;
      Create_DB_Num : UInt;
      Busy_Write : Bool;
      Busy_Read : Bool;
      Status_BLKMOV_Save_1 : Int;
      Status_BLKMOV_Recover_1 : Int;
      speicherbereich : Word;
      testpointer : "ANY_POINTER";
      trueval { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool := true;
      FN_Busy {OriginalPartName := 'F_TRIG_1500'; LibVersion := '1.0'} : F_TRIG;
  END_VAR


  VAR_TEMP
      pSourceDB : Any;
      ptSourceDB AT pSourceDB : "ANY_POINTER";
      pSaveDB : Any;
      ptSaveDB AT pSaveDB : "ANY_POINTER";
      Status : Int;
      Status_attr : Int;
      Status_crea : Int;
      Status_Attr_DB : Int;
      Status_BLKMOV_Save : Int;
      Status_BLKMOV_Recover : Int;
      DB_Lenght : UDInt;
      Attrib_RCV : UDInt;
      Anzahl_Werte : Word;
      InitBool : Bool;
      DB_save_Length : UDInt;
      DB_save_Attrib : Byte;
      Attr_status : Int;
      Attr_status_st : Struct
        Ladespeicher : Bool;
        writeprotect : Bool;
        remanent : Bool;
        ladeundarbeitspeicher : Bool;
      END_STRUCT;
  END_VAR




BEGIN
        #pSourceDB := #DB_TO_SAVE;
       
        #speicherbereich := DWORD_TO_WORD(ROR(IN := #ptSourceDB.Startadresse, N := 24));
       
        (*Pointer aufbereiten für kompletten DB*)
            #ptSourceDB.SyntaxID := B#16#10;
            #ptSourceDB.Bereichstyp := 2;
            #Status_Attr_DB := ATTR_DB(REQ := True,
                                      DB_NUMBER := #ptSourceDB.DB_Nr,
                                      DB_LENGTH => #DB_Lenght,
                                      ATTRIB => #Attrib_RCV);
            #Anzahl_Werte := UDINT_TO_WORD(#DB_Lenght);
            #ptSourceDB.Anzahl_Werte := UDINT_TO_UINT(#Anzahl_Werte);
            #ptSourceDB.Startadresse := DW#16#84000000;
           
           
        #ptSaveDB := #ptSourceDB; //Source/Save Pointer abgleichen
        #ptSaveDB.DB_Nr := #DB_NR_Loadmem;
        #Attr_status := ATTR_DB(REQ:=True, DB_NUMBER:=#ptSaveDB.DB_Nr, DB_LENGTH=>#DB_save_Length, ATTRIB=>#DB_save_Attrib);
        #Attr_status_st.Ladespeicher := #DB_save_Attrib.%X0; // Nachsehen ob DB zur Sicherung existiert.
        #Attr_status_st.writeprotect := #DB_save_Attrib.%X1;
        #Attr_status_st.remanent := #DB_save_Attrib.%X2;
        #Attr_status_st.ladeundarbeitspeicher := #DB_save_Attrib.%X3;
       
        // Vielleicht will man den DB mal aus dem Programm gesteuert löschen.
        #Status := DELETE_DB(REQ := #DeleteDB, DB_NUMBER := LINT_TO_UINT(60000), BUSY => #DelBusy);
        #DeleteDB := false;
       
        (* Wenn DB nicht im Ladespeicher und auch keine DB Generierung im Gang
        Dann Einen DB auf der Karte erstellen um ihn als Sicherung zu nutzen *)
        IF NOT #Attr_status_st.Ladespeicher AND NOT #Create_DB_Busy THEN
            #CreateDB := true;
        ELSIF #Create_DB_Busy THEN // Generierung im Gang Init Bool setzen da dieser DB nicht zurückgesichert werden soll
            #CreateDB := false;
            POKE_BOOL(area := 16#84,
                      dbNumber := #ptSourceDB.DB_Nr,
                      byteOffset := 0,
                      bitOffset := 0,
                      value := TRUE);
        END_IF;
       
        // Erstes Bit im zu sichernden DB überprüfen, wenn 0 dann soll DB restored werden.
        #InitBool := PEEK_BOOL(area := 16#84, dbNumber := #ptSourceDB.DB_Nr, byteOffset := 0, bitOffset := 0);
       
        #Status_crea := CREATE_DB(REQ := #CreateDB,
                                  LOW_LIMIT := #ptSaveDB.DB_Nr,
                                  UP_LIMIT := #ptSaveDB.DB_Nr,
                                  COUNT := 65534, // DB in maximaler Grösse. SD Karten kosten nix und es muss nicht neu generiert werden bei Grössenänderung
                                  ATTRIB := b#8#1,
                                  SRCBLK:=#pSourceDB, BUSY => #Create_DB_Busy,
                                  DB_NUM => #Create_DB_Num);
       
        #testpointer := #ptSaveDB; // Nur für Testzwecke. Kann am Schluss gelöscht werden.
       
        #Status_BLKMOV_Save := WRIT_DBL(REQ := #SaveDB AND NOT #Create_DB_Busy, // DB inhalt sichern
                                        SRCBLK := #pSourceDB,
                                        BUSY => #Busy_Write,
                                        DSTBLK => #pSaveDB);
       
        IF #Status_BLKMOV_Save <> w#16#7000 THEN
            #Status_BLKMOV_Save_1 := #Status_BLKMOV_Save;
        END_IF;
       
        IF NOT (#Busy_Write OR #Create_DB_Busy) THEN
            #SaveDB := FALSE;
        END_IF;
       
        // DB wurde initialisiert Daten aus Sicherungsdb wiederherstellen.
        IF NOT #InitBool THEN
            #RecoverDB := true;
        END_IF;
       
        #Status_BLKMOV_Recover := READ_DBL(REQ := #RecoverDB AND NOT #Create_DB_Busy,
                                          SRCBLK := #pSaveDB,
                                          BUSY => #Busy_Read,
                                          DSTBLK =>#pSourceDB);
       
        IF #Status_BLKMOV_Recover <> w#16#7000 THEN
            #Status_BLKMOV_Recover_1 := #Status_BLKMOV_Recover;
        END_IF;
       
        #FN_Busy(CLK:=#Busy_Read);
       
       
        IF #FN_Busy.Q THEN
            #RecoverDB := FALSE;
        POKE_BOOL(area := 16#84,
                                  dbNumber := #ptSourceDB.DB_Nr,
                                  byteOffset := 0,
                                  bitOffset := 0,
                                  value:=TRUE);
        END_IF;
       
       
       
END_FUNCTION_BLOCK

Ich hab ihn schon auf CPUs mit diversen 1.8er Firmwares und 2.0er Firmware ausprobiert.

Der DB der Gesichert werden soll muss an erster Speicherstelle ein Bool haben das nicht verwendet wird. Dieses wird durch den Baustein auf FALSE überprüft. Wenn es FALSE (z.B. durch einen Reinit von TIA) ist, wird falls vorhanden der Inhalt des LadespeicherDBs zurückgelesen.

mfG René

Viewing all articles
Browse latest Browse all 46421


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>