DBs auf MMC kopieren VIPA

Maagic7

Level-2
Beiträge
384
Reaktionspunkte
180
Zuviel Werbung?
-> Hier kostenlos registrieren
DB's auf MMC Datei kopieren bei VIPA CPU's ist nicht ganz so einfach wie es zuerst aussieht. Es gibt dafür eine VIPA spezifischen SFC 212 WriteFile, damit ist es aber leider nocht nicht ganz getan, da die Datei vorher geöffnet werden muss, ein FileSeek auf die Startadresse durchgeführt, die Daten geschrieben werden müssen und dann das File wieder geschlossen werden muss.
Ein weiteres Problem: SFC212 kann nur max einen Sektor (512 Bytes auf einmal schreiben); längere DB's müssen dann segmentiert geschrieben werden, wobei der FilePointer (Seek) richtig gesetzt sein muss.

Hier mein FB212, der nun endlich funktinoiert und dieses Problem löst

Code:
FUNCTION_BLOCK FB 212
TITLE =Daten von DB sektorübergreifend auf MMC schreiben (VIPA )
//Daten von DB sektroübergreifend in File auf MMC schreiben. (nur VIPA Speed7)
//
//Dieser FB läuft nur auf VIPA Speed7-CPUs, für standard CPUs ist ein anderer 
//Baustein notwendig. 
//
//Dieser Baustein funktioniert nicht für Siemens-CPUs, da es sich um VIPA 
//spezielle Funktionen handelt. Der Vorteil gegenüber den Siemens-CPUs ist 
//jedoch, daß VIPA CPUs standard MMC verwenden, die am PC mit jedem gängigen 
//Kartenlesegerät gelesen ung beschrieben werden können. Siemens verwendet eine 
//eigene Formatierung der MMC, somit können diese nicht ohne weiteres glesen 
//werden.
//
//Verwendete Bausteine (VIPA SFC), die Beschreibung der SFC befindet sich im VIPA 
//Handbuch HB140 im Kapitel 10 ab Seite 12
//
//SFC208 - FILE_OPN : MMC create/open file
//SFC212 - FILE_WR  : MMC qrite file
//
//AUTOR: Stefan Maag, Dipl.-Ing. (FH) Elektrotechnik 
//DATUM: 9/2005
//
//AENDERUNGSVERMERKE:
//--------------------------------------------------------------------------------
//DATUM        NAME        AENDERUNG
//--------------------------------------------------------------------------------
//12.12.2016   S.Maag      Fehler in Kommentaren beseitigt
//
//07.03.2014   S.Maag      getestet und Fehler beseitigt, erstmals lauffähig
//--------------------------------------------------------------------------------
//
//HINWEISE/LIZENZBEDINGUNGEN 
//Der Baustein ist für jeden frei verwendbar. Die Verwendung erfolgt auf eigenes 
//Risko. Der Autor übernimmt keinerlei Haftung/Verantwortung für Schäden 
//jeglicher Art die durch Verwendung/Anwendung dieser Software entstehen. 
//Sollten Dritte diesen Baustein verändern und in Verkehr bringen, müssen Sie 
//dies unter AENDERUNGSVERMERKE dokumentieren. Damit soll ausgeschlossen werden, 
//daß modifizierte evtl. Fehlerhafte Bausteine auf dem ursprünglichen Autor 
//zugeschrieben werden.
AUTHOR : 'S.Maag'
FAMILY : Maagic7
VERSION : 0.1


VAR_INPUT
  DB_SOURCE : INT ;    //Nummer des Quell DB
  DB_ADDR : DINT ;    //Zieladr. im DB
  BYTES : DINT ;    //Anzahl Bytes
  FileName : STRING  [254 ];    //Filename im 8.3 Format (keine Sonderzeichen erlaubt)
  Handle : INT  := 2;    //Optional FileHandle = 0..3
  FileADDR : DINT  := L#-1;    //Otional = -1 (EOF), Startposition Byte Schreiben
END_VAR
VAR_OUTPUT
  ERROR : BOOL ;    //Fehler
  ERR_NR : WORD ;    
  DSP_SNR : INT ;    //Anzeige Schrittnummer Kopierablauf
  LAST_SNR : INT ;    
END_VAR
VAR_IN_OUT
  START : BOOL ;    
END_VAR
VAR
  SFC208_RET_OPEN : WORD ;    
  SFC209_RET_CREATE : WORD ;    
  SFC210_RET_CLOSE : WORD ;    
  SFC212_RET_WRITE : WORD ;    
  SFC213_RET_SEEK : WORD ;    
  FileOffset : DINT ;    
  DB_Offset : DINT ;    
  BytesPerCycle : DINT  := L#512;    //kopierbare Bytes je Zyklus
  BytesLeft : DINT ;    //noch zu kopierende Bytes
  BytesThisCycle : DWORD ;    
  SNR : INT ;    
  ORIGIN : INT ;    //Ursprung für SFC213 File-Seek
  BUSY : BOOL ;    
END_VAR
VAR_TEMP
  QuellPtr : ANY ;    
  VKE1 : BOOL ;    
END_VAR
BEGIN
NETWORK
TITLE =




NETWORK
TITLE =

      SET   ; 
      =     #VKE1; // VKE=1 für Parameterübergabe erzeugen
NETWORK
TITLE =Standard Ablaufsteuerung mit INIT und CLR-Zweig


      L     #SNR; // Schrittnummer
      SPL   CLR; // Sprungziel bei SNR>max
      SPA   INIT; // 0-Schritt, Initialisierung
      SPA   S1; // Startschritt
      SPA   S2; // open File
      SPA   S3; // FileSeek
      SPA   S4; // Kopierschleife
      SPA   S5; // Kopierschleife
      SPA   CLOS; // File schließen


CLR:  SET   ; // CLR
// hier die bei CLR zu löschenden Merker eintragen

      R     #START; // Startmerker löschen

      L     1; // Schrittnummer 
      T     #SNR; // auf Startschritt stellen
      T     #DSP_SNR; // Schrittnummer Anzeige
      SPA   END; 

INIT: SET   ; // Initalisierung
      CLR   ; 
      SPA   CLR; 


NETWORK
TITLE =Schrittweiterschaltung, bzw. Bausteinende

NEXT: L     #SNR; // NEXT : Schrittnummer auf nächsten
      +     1; // Schritt
      T     #SNR; 

END:  L     #SNR; // Sprungmarke für Baustein ENDE
      T     #DSP_SNR; // Schrittnummer Anzeige
      L     1; // Wenn Ablauf läuft, dann ENO-Ausgang = 1
      >I    ; 
      SAVE  ; 
      CLR   ; 
      BEA   ; 

NETWORK
TITLE =Startschritt, File öffnen
//Rückmeldung von SFC220
//
//Diagnosemeldungen
//
//0000h : kein Fehler
//0001h : Datei existiert schon, ist unfragmentiert und die Längenangabe ist
//        identisch oder größer. Diese Meldung kommt immer sobald Sie eine
//        schon bestehende Datei öffnen.
//
//8001h : Es ist keine oder eine falsche MMC gesteckt.
//8011h : FILENAME fehlerhaft (nicht im Format 8.3 oder Sonderzeichen)
//8100h : Der angegebene HANDLE ist ungültig
//
//8002h : Es befindet sich keine FAT auf der MMC.
//A001h : Es wurde kein Dateiname angegeben.
//A002h : Der angegebene Dateiname ist falsch.
//A003h : Die Datei existiert schon, aber die unter Filesize angegebene
//        Größe ist zu klein.
//A004h : Die Datei existiert schon, ist aber fragmentiert und kann nicht
//        geöffnet werden.
//A005h Es ist kein ausreichender Speicherplatz auf der MMC vorhanden.
//A006h Es existiert kein freier Eintrag im Root-Verzeichnis. Abhängig von
//der eingesetzten MMC dürfen sich mindestens 16 bis maximal
//512 Einträge im Root-Verzeichnis befinden.
//B000h Es ist ein interner Fehler aufgetreten.
S1:   U     #START; // Daten kopieren Start
      SPBN  END; 

      R     #ERROR; // Fehlerausgangsbit löschen

      L     0; 
      T     #ERR_NR; 
      T     #LAST_SNR; 

      L     #DB_ADDR; // Startadresse im DB
      T     #DB_Offset; 

      L     #FileADDR; // Offsetadresse im File
      L     L#-1; // Vergleichswert für EOF
      ==D   ; 
      SPB   eof; 

// Parameter FC213 FileSeek für Schreiben ab BytePosition
      L     #FileADDR; // übergebene FileAddresse
      T     #FileOffset; // als ByteOffset
      L     0; // vom FileAnfang
      T     #ORIGIN; // (ORIGIN=0) übernehmen 
      SPA   weit; 

// Parameter SFC213 FileSeek für Schreiben am Filende
eof:  L     L#0; // ByteOffset vom Fileende aus
      T     #FileOffset; 
      L     2; // Kennung für SEEK FileEnde
      T     #ORIGIN; 

weit: L     #BYTES; // noch zu kopierende Bytes
      T     #BytesLeft; 

      CALL SFC  209 (// create File
           Req                      := #VKE1,
           Media                    := 0,
           Filename                 := #FileName,
           Handle                   := #Handle,
           RetVal                   := #SFC209_RET_CREATE,
           Busy                     := #BUSY);

      U     #BUSY; 
      SPB   END; 
      SPA   NEXT; 

NETWORK
TITLE =Open File

S2:   NOP   0; 

      CALL SFC  208 (// open file
           Req                      := #VKE1,
           Media                    := 0,
           Filename                 := #FileName,
           Handle                   := #Handle,
           RetVal                   := #SFC208_RET_OPEN,
           Busy                     := #BUSY);

      U     #BUSY; 
      SPB   END; 

      T     #ERR_NR; 
      L     W#16#1; // Wenn <1, dann kein Fehler
      <=I   ; 
      SPB   NEXT; 
      SPA   CLOS; // File wieder schließen


NETWORK
TITLE =Startposition im File setzen
//Rückmeldungen von SFC213 FileSeek
//
//0000h : Ok, Offset beinhaltet die Aktuelle Lese/Schreib-Position
//7000h : Req = 0, Busy = 0 (nichts ist zu tun)
//7001h : Req = 1, 1. Aufruf
//7002h : Baustein wird bearbeitet
//8100h : Der angegebene Handle ist ungültig
//9001h : Für diesen Handle ist keine Datei geöffnet
//9002h : Eine andere Funktion wurde über den Handle aufgerufen und
//        ist fertig.
//9003h : Eine andere Funktion wurde über den Handle aufgerufen und
//        ist nicht fertig.
//A000h : Systeminterner Fehler aufgetreten
//A004h : Origin-Parameter ist fehlerhaft
//A100h : Allgemeiner Filesystem-Fehler (z.B. keine MMC gesteckt)
S3:   CALL SFC  213 (// FileSeek
           Req                      := #VKE1,
           Handle                   := #Handle,
           Origin                   := #ORIGIN,// 0=BOF,  1=CurrentPosition, 2=EOF
           RetVal                   := #SFC213_RET_SEEK,
           Busy                     := #BUSY,
           Offset                   := #FileOffset);

      U     #BUSY; 
      SPB   END; 

      L     #SFC213_RET_SEEK; // Rückgabewert auf Fehler prüfen
      T     #ERR_NR; // und Rückgabewert als letzte Fehlernummer
      L     0; // an FB-Ausgang übergeben
      <>I   ; 
      S     #ERROR; 
      SPB   CLOS; // FileClose

      SPA   NEXT; 

NETWORK
TITLE =Start der Block/Sektorweisen Kopierschleife
//In einem Kopierzyklus kann immer nur ein Sektor kopiert werden, 
//Sektorübergreifendes Lesen/Schreiben ist nicht möglich. Ein Sektor ist 
//üblicherweise 512 Bytes groß (für #BytesPerCycle ist 512 als Anfangswert 
//eingetragen)
S4:   L     #BytesLeft; // noch zu kopierende Bytes
      L     #BytesPerCycle; 
      >D    ; // Wenn noch mehr zu als BytesPerCycle zu kopieren
      SPB   save; // ist, dann max Anzahl = BytesPerCycle kopieren
      TAK   ; // sonst RestBytes = BytesLeft kopieren
save: T     #BytesThisCycle; // Anzahl der Bytes in diesem Kopierzyklus
      L     L#0; // Wenn die zu kopierenden Bytes = 0 sind,
      <=D   ; // dann liegt ein Fehler vor
      S     #ERROR; // Somit Fehlerausgang setzen
      SPB   CLOS; // und File schließen

      SPA   NEXT; 

NETWORK
TITLE =Block/Sektor kopieren
//Rückmeldungen von SFC212
//
//0XXXh : 0 = Ok, 0XXX = Länge geschriebener Daten
//7000h : Req = 0, Busy = 0 (nichts ist zu tun)
//7001h : Req = 1, 1. Aufruf
//7002h : Baustein wird bearbeitet
//8010h : Pointer in Data ist vom Typ BOOL
//8011h : Pointer in Data kann nicht dekodiert werden
//        (z.B. DB nicht geladen)
//8012h : Datenlänge ist größer als 512Byte
//8100h : Der angegebene Handle ist ungültig
//9001h : Für diesen Handle ist keine Datei geöffnet
//9002h : Eine andere Funktion wurde über den Handle aufgerufen und
//        ist fertig.
//9003h : Eine andere Funktion wurde über den Handle aufgerufen und
//        ist nicht fertig.
//A000h : Systeminterner Fehler aufgetreten
//A003h : interner Fehler
//A004h : Die Datei ist schreibgeschützt
//A100h : Allgemeiner Filesystem-Fehler (z.B. keine MMC gesteckt)
S5:   NOP   0; 

      LAR1  P##QuellPtr; // Any-Pointer des zu kopierenden Datenbereichs

      L     B#16#10; // Syntax-ID, immer 10h für S7
      T     LB [AR1,P#0.0]; 

      L     B#16#2; // Datentyp = Bytes = 2h
      T     LB [AR1,P#1.0]; 

      L     #BytesThisCycle; // Wiederholfaktor, Anzahl
      T     LW [AR1,P#2.0]; 

      L     #DB_SOURCE; // Nr des Ziel-DB
      T     LW [AR1,P#4.0]; 

      L     #DB_Offset; 
      SLD   3; 
      L     P#DBX 0.0; // Pointer auf DBW0
      +D    ; // Summe Pointer = DW_Pointer
      T     LD [AR1,P#6.0]; // Pointer auf Datenbereich

      CALL SFC  212 (// VIPA FileWrite
           Req                      := #VKE1,
           Handle                   := #Handle,
           Data                     := #QuellPtr,
           RetVal                   := #SFC212_RET_WRITE,
           Busy                     := #BUSY);

      U     #BUSY; // solange der Kopiervorgang
      SPB   END; // noch läuft -> Bausteinende

      L     #SFC212_RET_WRITE; // Rückgabewert SFC221 (0xxx = ByteAnzahl)
      T     #ERR_NR; 
      L     W#16#1000; // auf Fehler überwachen
      >=I   ; // wenn <> 0, dann Fehler
      S     #ERROR; // Fehlerausgang FB setzen
      SPB   CLOS; // File schließen

      L     #BytesLeft; // noch zu kopierende Bytes
      L     #BytesThisCycle; // Bytes in diesem Zyklus kopiert
      -D    ; 
      T     #BytesLeft; // Rest der noch zu koierenden Bytes

      U     <=0; // Wenn alle Bytes kopiert wurden!
      SPB   NEXT; // Nächster Schritt File schließen

      L     #DB_Offset; // DB Adresse für nächsten
      L     #BytesThisCycle; // Kopierzyklus berechnen
      +D    ; 
      T     #DB_Offset; 

      L     4; // Kopierschleife Wiederholen
      T     #SNR; 
      SPA   END; 
NETWORK
TITLE =Geöffnetes File schließen
//Rückmeldungen von SFC210
//
//0000h : Ok
//7000h : Req = 0, Busy = 0 (nichts ist zu tun)
//7001h : Req = 1, 1. Aufruf
//7002h : Baustein wird bearbeitet
//8100h : Der angegebene Handle ist ungültig
//9001h : Dem Handle ist kein Dateiname zugeordnet
//9002h : Eine andere Funktion wurde über den Handle aufgerufen und
//        ist fertig.
//9003h : Eine andere Funktion wurde über den Handle aufgerufen und
//        ist nicht fertig.
//A000h : Systeminterner Fehler aufgetreten
//A100h : Allgemeiner Filesystem-Fehler (z.B. keine MMC gesteckt)
CLOS: L     #SNR; 
      T     #LAST_SNR; 

      L     6; // Ablauf auf Schritt 5 setzen (=CLOSE), dadurch muß nur
      T     #SNR; // mit SPA angesprungen werden

      CALL SFC  210 (// VIPA SFC FileClose
           Req                      := #VKE1,
           Handle                   := #Handle,
           RetVal                   := #SFC210_RET_CLOSE,
           Busy                     := #BUSY);

      U     #BUSY; 
      SPB   END; 

      L     #SFC210_RET_CLOSE; // Rückgabewert auf Fehler überprüfen
      L     0; // 0 = kein Fehler
      <>I   ; 
      SPB   ERR; // Ablauf CLR

      SPA   NEXT; 

ERR:  S     #ERROR; // Fehlerausgang FB setzen
      L     #SFC210_RET_CLOSE; // Fehler an FB-Ausgang übergeben
      T     #ERR_NR; 
      SPA   CLR; 

END_FUNCTION_BLOCK
 
Zurück
Oben