-> 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
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