S7-1500 FileReadC FileWriteC: TIA Portal V15 MMC File Handling

David Krause10 min read
SiemensTechnical ReferenceTIA Portal
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

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.
The blocks appear under Instructions → Extended instructions → File handling. Older project libraries must be upgraded to V15 or later before the blocks can be inserted; otherwise the call will be flagged "Unknown FB" in the program editor.

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

  1. 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
  2. Populate the buffer. Move the payload into MyWriteData using MOVE_BLK, FILL_BLK, or program logic. Remember that the only legal DATA VARIANT is an Array of Byte.
  3. Insert FileWriteC. Drag it from Extended instructions → File handling. Wire REQ := writeTrigger, NAME := 'UserFiles\myFile.txt', DATA := "DataBlock1".MyWriteData, and the length.
  4. Trigger once per significant event. Drive REQ with a rising edge when a write is genuinely required. Continuous toggling on the SMC will shorten card lifetime.
  5. Read back with FileReadC. Insert the block, supply the same path, and point DATA to a byte array of equal or larger size. The block will return the number of bytes actually read.
  6. Reconstruct native types. If the payload originated as INT, REAL, or a STRUCT, serialize it into the byte buffer before writing and deserialize after reading.
  7. Monitor the status. Evaluate BUSY, DONE, ERROR, and STATUS in 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.

Absolute paths (e.g. 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.

Never tie 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 / DataLogWrite instead when high-frequency appends are needed (these blocks manage rotation and wear).
  • Use SMCInfo or the online diagnostics to monitor CardLifeRemaining on 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 yields STATUS = 16#7000 with 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 DONE returns immediately with STATUS = 16#7000 and no file appears.
  • The DONE counter 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

  1. Set REQ to FALSE; confirm BUSY = FALSE, STATUS = 16#7000.
  2. Pre-load MyWriteData with a known pattern (use Fill in the watch table: 16#AA for 16 bytes).
  3. Trigger REQ := TRUE; within one OB1 cycle BUSY rises to TRUE.
  4. Wait until DONE = TRUE and STATUS = 16#0000. Reset REQ := FALSE before the next trigger.
  5. Pull the SMC, open the file on a PC, verify the byte pattern is present.
  6. For the read side, write a different pattern from the PC, reinsert the SMC, trigger FileReadC.REQ, and verify MyReadData matches.

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/FileWriteC inside a multi-instance FB to centralize path handling, error mapping, and trigger gating.

Verification Checklist

  • FileWriteC produces a file under \UserFiles\ on the SMC with the expected byte count.
  • FileReadC returns STATUS = 16#0000 and LEN matches the on-card size.
  • Deserialized values equal the originally written ones across at least three cycles.
  • SMC diagnostics show no CardLifeRemaining alarm 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.

Back to blog