Dateizugriff aus der SPS
In diesem Beispiel wird die Anwendung der SPS-Funktionsbausteine für den Dateizugriff aus der Tc2_System-Bibliothek vorgestellt. Mit Hilfe der vorhandenen Funktionsbausteine wurde ein neuer Funktionsbaustein FB_FileCopy realisiert. Mit dem FB_FileCopy-Funktionsbaustein können Binärdateien auf dem lokalen TwinCAT System oder zwischen einem lokalen und einem remote-TwinCAT-System kopiert werden.
Die kompletten Sourcen zu dem Beispielprojekt können hier entpackt werden: FileCopyExample.zip
Mit den FB_FileCopy-Funktionsbaustein kann nicht auf Netzwerklaufwerke zugegriffen werden. |
Bei einer steigenden Flanke am bExecute-Eingang des FB_FileCopy-Bausteines werden folgende Schritte ausgeführt:
a) Öffnen der Quell- und Ziel-Datei
b) Lesen der Quell-Datei in einen Puffer
c) Schreiben der gelesenen Bytes aus dem Puffer in die Ziel-Datei
d) Überprüfen ob das Ende der Quell-Datei erreicht wurde. Wenn nicht dann b) und c) wiederholen. Wenn ja, dann zu e) springen
e) Schließen der Quell- und Ziel-Datei
Die Datei wird stückweise kopiert. Die Größe des Puffers wurde im Beispiel auf 1000 Byte festgelegt, kann aber geändert werden.
SPS-Programm
Deklarationsteil
FUNCTION_BLOCK FB_FileCopy
VAR_INPUT
sSrcNetId : T_AmsNetId;
sSrcPathName : T_MaxString;
sDestNetId : T_AmsNetId;
sDestPathName : T_MaxString;
bExecute : BOOL;
tTimeOut : TIME := DEFAULT_ADS_TIMEOUT;
END_VAR
VAR_OUTPUT
bBusy : BOOL;
bError : BOOL;
nErrId : UDINT;
END_VAR
VAR
fbFileOpen : FB_FileOpen;
fbFileClose : FB_FileClose;
fbFileRead : FB_FileRead;
fbFileWrite : FB_FileWrite;
hSrcFile : UINT := 0;(* File handle of the source file *)
hDestFile : UINT := 0;(* File handle of the destination file *)
Step : DWORD;
RisingEdge : R_TRIG;
buffRead : ARRAY[1..1000] OF BYTE;(* Buffer *)
cbReadLength : UDINT := 0;
END_VAR
Implementierung
RisingEdge(CLK:=bExecute);
CASE Step OF
0: (* Idle state *)
IF RisingEdge.Q THEN
bBusy := TRUE;
bError:= FALSE;
nErrId:=0;
Step := 1;
cbReadLength:=0;
hSrcFile:=0;
hDestFile:=0;
END_IF
1: (* Open source file *)
fbFileOpen( bExecute := FALSE );
fbFileOpen( sNetId := sSrcNetId, sPathName := sSrcPathName,
nMode := FOPEN_MODEREAD OR FOPEN_MODEBINARY,
ePath := PATH_GENERIC, tTimeout := tTimeOut, bExecute := TRUE );
Step := Step + 1;
2:
fbFileOpen( bExecute := FALSE );
IF NOT fbFileOpen.bBusy THEN
IF fbFileOpen.bError THEN
nErrId := fbFileOpen.nErrId;
bError := TRUE;
Step := 50;
ELSE
hSrcFile := fbFileOpen.hFile;
Step := Step + 1;
END_IF
END_IF
3: (* Open destination file *)
fbFileOpen( bExecute := FALSE );
fbFileOpen( sNetId := sDestNetId, sPathName := sDestPathName,
nMode := FOPEN_MODEWRITE OR FOPEN_MODEBINARY,
ePath := PATH_GENERIC, tTimeout := tTimeOut, bExecute := TRUE );
Step := Step+1;
4:
fbFileOpen( bExecute := FALSE );
IF NOT fbFileOpen.bBusy THEN
IF fbFileOpen.bError THEN
nErrId := fbFileOpen.nErrId;
bError := TRUE;
Step := 50;
ELSE
hDestFile := fbFileOpen.hFile;
Step := Step + 1;
END_IF
END_IF
5: (* Read data from source file *)
cbReadLength := 0;
fbFileRead( bExecute:= FALSE );
fbFileRead( sNetId:=sSrcNetId, hFile:=hSrcFile,
pReadBuff:= ADR(buffRead), cbReadLen:= SIZEOF(buffRead),
bExecute:=TRUE, tTimeout:=tTimeOut );
Step := Step + 1;
6:
fbFileRead( bExecute:= FALSE );
IF NOT fbFileRead.bBusy THEN
IF fbFileRead.bError THEN
nErrId := fbFileRead.nErrId;
bError := TRUE;
Step := 50;
ELSE
cbReadLength := fbFileRead.cbRead;
Step := Step + 1;
END_IF
END_IF
7: (* Write data to destination file *)
fbFileWrite( bExecute := FALSE );
fbFileWrite( sNetId:=sDestNetId, hFile:=hDestFile,
pWriteBuff:= ADR(buffRead), cbWriteLen:= cbReadLength,
bExecute:=TRUE, tTimeout:=tTimeOut );
Step := Step + 1;
8:
fbFileWrite( bExecute := FALSE );
IF NOT fbFileWrite.bBusy THEN
IF fbFileWrite.bError THEN
nErrId := fbFileWrite.nErrId;
bError := TRUE;
Step := 50;
ELSE
IF fbFileRead.bEOF THEN (* Check if the EOF flag ist set *)
Step := 50; (* Cleanup: close the destination and source files *)
ELSE
Step := 5; (* Repeat reading/writing *)
END_IF
END_IF
END_IF
30: (* Close the destination file *)
fbFileClose( bExecute := FALSE );
fbFileClose( sNetId:=sDestNetId, hFile:=hDestFile, bExecute:=TRUE, tTimeout:=tTimeOut );
Step := Step + 1;
31:
fbFileClose( bExecute := FALSE );
IF NOT fbFileClose.bBusy THEN
IF fbFileClose.bError THEN
nErrId := fbFileClose.nErrId;
bError := TRUE;
END_IF
Step := 50;
hDestFile := 0;
END_IF
40: (* Close source file *)
fbFileClose( bExecute := FALSE );
fbFileClose( sNetId:=sSrcNetId, hFile:=hSrcFile, bExecute:=TRUE, tTimeout:=tTimeOut );
Step := Step + 1;
41:
fbFileClose( bExecute := FALSE );
IF NOT fbFileClose.bBusy THEN
IF fbFileClose.bError THEN
nErrId := fbFileClose.nErrId;
bError := TRUE;
END_IF
Step := 50;
hSrcFile := 0;
END_IF
50: (* Error or ready => Cleanup *)
IF ( hDestFile <> 0 ) THEN
Step := 30; (* Close the destination file*)
ELSIF (hSrcFile <> 0 ) THEN
Step := 40; (* Close the source file *)
ELSE
Step := 0; (* Ready *)
bBusy := FALSE;
END_IF
END_CASE