Overview of FileReadC and FileWriteC in TIA Portal V15
Starting with TIA Portal V15 (STEP 7 V15), Siemens introduced the FileReadC and FileWriteC extended instructions for the S7-1200/S7-1500 families. These blocks allow ASCII file I/O directly to and from a SIMATIC memory card (SMC) inserted in the CPU, eliminating the need for separate recipe or DataLog functions when only a flat byte stream needs to be persisted.
Typical use cases include:
- Storing machine recipes as raw byte streams
- Capturing periodic log or report snapshots
- Archiving trace buffers, alarm histories, or production counters
- Exchanging configuration data with an external tool that reads the SMC offline
The blocks are asynchronous; they are triggered with a positive edge on REQ and report completion on DONE, BUSY, and ERROR/STATUS. Refer to the official FileReadC documentation (TIA Portal cloud manual collection) and FileWriteC documentation (TIA Portal cloud manual collection) for the canonical block description.
CPU and Firmware Prerequisites
| Component | Minimum Requirement | Notes |
|---|---|---|
| TIA Portal / STEP 7 | V15 (any update) | Blocks are not present in V14 SP1 or earlier. |
| S7-1500 CPU firmware | V2.5 or later recommended | File-handling extended instructions were activated for the S7-1500 family with firmware V2.5. |
| S7-1200 CPU firmware | V4.2 or later | Same family of blocks; minor parameter differences possible. |
| ET 200SP CPU | V2.5 or later | Compatible with F-readC/F-writeC libraries only via distributed I/O; file system is local to the CPU. |
| SIMATIC Memory Card | SMC required (not SC card) | The CPU file system only mounts on SMC; SD cards without SMC support will not expose UserFiles\. |
| Free CPU file system space | > file size + ~10% overhead | Recipe or log use should leave headroom; data blocks consume separate space. |
Block Interface Reference
Both FileReadC and FileWriteC share a similar parameter signature; the differences are listed below.
| Parameter | Direction | Type | Description |
|---|---|---|---|
REQ |
IN | BOOL | Rising edge starts the asynchronous operation. |
DONE |
OUT | BOOL | TRUE for one cycle when the operation completes without error. |
BUSY |
OUT | BOOL | TRUE while the operation is in progress. |
ERROR |
OUT | BOOL | TRUE when the operation terminates with an error. |
STATUS |
OUT | WORD | Error code; 16#0000 = success, 16#7000 = no operation pending, 16#7001 = BUSY. See error table below. |
NAME |
IN | VARIANT / STRING | File name including the relative path inside the CPU file system, e.g. 'UserFiles\recipe.bin'. |
DATA |
IN/OUT | VARIANT | Source/destination data area. Must be Array of Byte for both blocks.
|
LEN (write) |
IN | DINT / UDINT | Number of bytes to write from DATA. |
LEN (read) |
OUT | DINT / UDINT | Number of bytes actually read into DATA. |
Step-by-Step: Implementing FileWriteC and FileReadC
-
Create the byte buffer. In a global data block (e.g.
DataBlock1), declare the source/target array:DATA_BLOCK "DataBlock1" VAR MyWriteData : ARRAY[0..255] OF BYTE; MyReadData : ARRAY[0..255] OF BYTE; END_VAR END_DATA_BLOCK -
Populate the buffer. Move the payload into
MyWriteDatausingMOVE_BLK,FILL_BLK, or program logic. Remember that the only legalDATAVARIANT is anArray of Byte. -
Insert
FileWriteC. Drag it from Extended instructions → File handling. WireREQ := writeTrigger,NAME := 'UserFiles\myFile.txt',DATA := "DataBlock1".MyWriteData, and the length. -
Trigger once per significant event. Drive
REQwith a rising edge when a write is genuinely required. Continuous toggling on the SMC will shorten card lifetime. -
Read back with
FileReadC. Insert the block, supply the same path, and pointDATAto a byte array of equal or larger size. The block will return the number of bytes actually read. -
Reconstruct native types. If the payload originated as
INT,REAL, or aSTRUCT, serialize it into the byte buffer before writing and deserialize after reading. -
Monitor the status. Evaluate
BUSY,DONE,ERROR, andSTATUSin a watch table or HMI to confirm end of operation.
Path Conventions: The UserFiles Folder
The NAME parameter must always be a relative path inside the CPU file system. The folder UserFiles is the only writable area exposed to user-level instructions. Examples:
'UserFiles\recipe.bin'
'UserFiles\logs\2024_05.csv'
'UserFiles\backup\cfg_001.bin'
Subdirectories must exist before writing; the block will not create them. They can be created offline by inserting the SMC into a card reader and creating the folders on the FAT partition, or online with third-party Web-API tools.
D:\UserFiles\...) and UNC paths are rejected with STATUS = 16#8090. Use the relative form starting with UserFiles\.Data Type Limitation and Serialization Strategy
The single most common field issue is error 16#8A51: Invalid data type of the "DATA" parameter. It is raised whenever DATA is bound to anything other than an Array of Byte (or a single BYTE tag in some firmware revisions). The following types all trigger 16#8A51:
-
Array of INT,Array of REAL,Array of BOOL -
STRING,WSTRING -
UDT/STRUCT
To persist richer data, serialize the value to a byte buffer before writing. Siemens provides several mechanisms:
| Source type | Recommended conversion | Notes |
|---|---|---|
INT / DINT
|
Serialize / Deserialize from the Extended instructions → Serialization palette. |
Outputs big-endian or little-endian byte streams. |
REAL / LREAL
|
Same Serialize / Deserialize FBs. |
IEEE-754 raw bytes; consume with the matching Deserialize call. |
STRING |
Use the Serialize block; concatenate manually for variable-length records. |
Store length prefix if records are mixed-size. |
UDT / PLC data type |
Serialize the whole UDT as one block, then MOVE_BLK into the byte array. |
Layout is deterministic; UDTs are stored contiguously. |
| Recipe structures | Serialize each element into a fixed-size byte image; document the schema in the file header. | Header helps migration between firmware revisions. |
A minimal STL/SCL example for an INT:
// Write side
"MyLib".Serialize(IN := recipeWord,
OUT := %DB20.DBX0.0 BYTE 2); // 2 bytes little-endian
FileWriteC(REQ := writeTrig,
NAME := 'UserFiles\recipe.bin',
DATA := "DataBlock1".MyWriteData,
LEN := 2);
// Read side
FileReadC(REQ := readTrig,
NAME := 'UserFiles\recipe.bin',
DATA := "DataBlock1".MyReadData,
LEN => actualLen);
"MyLib".Deserialize(IN := %DB20.DBX0.0 BYTE 2,
OUT => recipeWord);
Memory Card Write-Cycle Considerations
SMC media is NAND flash and has a finite program/erase budget. Siemens specifies a typical endurance of 100,000 to 1,000,000 write cycles per sector depending on card generation. For continuous logging, the wear leveling is sufficient for years, but bursty or mis-triggered writes will exhaust a sector prematurely.
REQ directly to a fast cyclic flag (e.g. Clock_1Hz) when writing to the SMC. Use event-driven triggers: end of batch, recipe change, alarm threshold crossed, or operator command from the HMI.Mitigation checklist:
- Buffer records in a RAM DB and flush in groups of N to amortize writes.
- Use
DataLogCreate/DataLogWriteinstead when high-frequency appends are needed (these blocks manage rotation and wear). - Use
SMCInfoor the online diagnostics to monitorCardLifeRemainingon newer firmware. - Schedule the SMC for periodic replacement in plants with heavy logging.
PLCSIM Advanced Behavior and Limitations
When the blocks are exercised inside PLCSIM Advanced, the virtual CPU maps its file system to a folder on the host PC (default %USERPROFILE%\Documents\Siemens\SIMATIC_MC). Field reports confirm the following constraints:
-
Folder name must be
UserFiles. Any other folder name (Files,Data, etc.) silently yieldsSTATUS = 16#7000with no file created or read. -
Use a relative path:
'UserFiles\data.txt'. Absolute paths pointing at the host disk root are not accepted. -
Some PLCSIM Advanced versions (e.g. 2.0) do not implement the file-handling blocks at all. Upgrade to PLCSIM Advanced 4.0 or later if
DONEreturns immediately withSTATUS = 16#7000and no file appears. - The
DONEcounter increments because the block call itself completes; this does not guarantee that data hit the host file system. Always verify by inspecting the folder.
// Correct PLCSIM Advanced usage
FileReadC(REQ := readTrig,
NAME := 'UserFiles\data.txt',
DATA := "DataBlock1".MyReadData,
LEN => actualLen);
// Wrong: will produce no error but no file activity
FileReadC(REQ := readTrig,
NAME := 'data.txt', // missing UserFiles\\
DATA := "DataBlock1".MyReadData,
LEN => actualLen);
STATUS and Error Code Reference
| STATUS (hex) | Meaning | Typical cause / remedy |
|---|---|---|
0000 |
Operation successful. | No action. |
7000 |
No operation in progress (idle). | Trigger REQ with a rising edge. |
7001 |
Operation in progress (BUSY = TRUE). |
Wait for DONE or ERROR; do not retrigger. |
8090 |
Invalid file name / path. | Use relative path starting with UserFiles\; check length limits. |
8091 |
File not found (read). | Verify the file exists on the SMC. |
8092 |
Access denied / locked. | Another process is holding the file; check Web server or online connection. |
80A0 |
Internal error (file system). | Reformat / replace the SMC; cycle power. |
80A1 |
Not enough memory on the card. | Free space, switch to a larger SMC, or trim payload. |
80A2 |
Write protect / read-only card. | Remove write-protection slider on the SMC. |
8A51 |
Invalid data type of the DATA parameter. |
Bind DATA only to an Array of Byte; serialize other types first. |
80B0 - 80BF
|
Length out of range. | Ensure LEN matches the array size declared in DATA. |
80C0 - 80CF
|
Card not present / not initialized. | Insert SMC, wait for CPU RUN, or check CPU diagnostics buffer. |
Sample Watch-Table Commissioning Sequence
- Set
REQtoFALSE; confirmBUSY = FALSE,STATUS = 16#7000. - Pre-load
MyWriteDatawith a known pattern (useFillin the watch table:16#AAfor 16 bytes). - Trigger
REQ := TRUE; within one OB1 cycleBUSYrises toTRUE. - Wait until
DONE = TRUEandSTATUS = 16#0000. ResetREQ := FALSEbefore the next trigger. - Pull the SMC, open the file on a PC, verify the byte pattern is present.
- For the read side, write a different pattern from the PC, reinsert the SMC, trigger
FileReadC.REQ, and verifyMyReadDatamatches.
Common Pitfalls and Field-Proven Workarounds
| Pitfall | Symptom | Workaround |
|---|---|---|
| Reading and writing into the same memory area | Self-overwritten data, corruption on read-back. | Use two distinct byte arrays for FileReadC and FileWriteC. |
Using BOOL / INT arrays as DATA
|
Immediate STATUS = 16#8A51. |
Serialize to byte stream first; never bind a non-byte VARIANT to DATA. |
| Calling from multiple OBs at high priority |
STATUS = 16#80B1, sporadic overruns. |
Serialize calls into a single OB1 (or dedicated cyclic OB at low priority) via a trigger semaphore. |
| Cyclic write every scan | Card wears out in days; possible STATUS = 16#80A2. |
Trigger only on event; consider DataLog blocks for high-frequency appends. |
| PLCSIM Advanced with mismatched folder name | Silent DONE, no file created. |
Always create UserFiles explicitly under SIMATIC_MC. |
Missing trailing \ in path |
Random 16#8090. |
Validate paths against the documentation; copy-paste is the safest. |
| Web server is reading the same file |
STATUS = 16#8092. |
Disable Web server download of UserFiles while writes are pending, or schedule writes during non-Web windows. |
Alternatives and When to Use Them
-
DataLog blocks (
DataLogCreate,DataLogWrite,DataLogClose): purpose-built for high-frequency append, automatic rotation, CSV support, and wear leveling. Prefer these for production logging. - Recipe functions from the "Recipes" library: keep recipes inside the PLC project and provide structured HMI access; no raw file I/O.
- Web API / OPC UA file methods: read the SMC file from a remote client without pulling the card.
-
ProDiag / user FBs: wrap
FileReadC/FileWriteCinside a multi-instance FB to centralize path handling, error mapping, and trigger gating.
Verification Checklist
-
FileWriteCproduces a file under\UserFiles\on the SMC with the expected byte count. -
FileReadCreturnsSTATUS = 16#0000andLENmatches the on-card size. - Deserialized values equal the originally written ones across at least three cycles.
- SMC diagnostics show no
CardLifeRemainingalarm after a stress run. - PLCSIM Advanced round-trip succeeds with the path
UserFiles\<name>. - Watch-table sequence has been captured and signed off.
FAQ
Why do I get error 16#8A51 when calling FileWriteC?
STATUS 16#8A51 means the DATA parameter is not bound to a byte array. Only Array of BYTE is accepted; arrays of INT, REAL, BOOL, STRING, or UDT must first be serialized into a byte buffer using the Serialize/Deserialize extended instructions.
What is the correct path for files on the SIMATIC Memory Card?
Use a relative path that starts with UserFiles\, for example 'UserFiles\recipe.bin'. Absolute paths, UNC paths, or paths to folders other than UserFiles will return STATUS 16#8090 or produce no file activity in PLCSIM Advanced.
How often can I safely call FileWriteC?
The SMC has a finite program/erase endurance of roughly 100,000 to 1,000,000 cycles per sector. Trigger FileWriteC only on real events (recipe change, end of batch, operator action) and avoid cyclic writes; for continuous logging, switch to the DataLog blocks which manage wear leveling.
Does FileReadC/FileWriteC work in PLCSIM Advanced?
Yes, but only in PLCSIM Advanced 4.0 or later and only when the file is placed in a folder literally named UserFiles inside the SIMATIC_MC directory. Using any other folder name silently returns STATUS 16#7000 with no file created or read.
Can I read back an Array of INT without serializing again?
No. The DATA parameter accepts only a byte array. After FileReadC completes, run the matching Deserialize block (or manual byte swap) to reconstruct the INT, REAL, or UDT values in the destination tag.