Problem Statement: Standalone Event Archiving on CPU 313C
When a SIMATIC S7-300 station has no permanently attached HMI, SCADA, or engineering station, plant owners still need a low-cost way to capture time-stamped process events (warnings, alarms, quality bits) for later analysis. The CPU 313C (order number 6ES7 313-5BF03-0AB0) ships with 32 KB of work memory and uses a Micro Memory Card (MMC) for load memory, making it a typical candidate for this kind of retrofit archive. The goal: on every rising edge of a status bit (for example M20.0), write the current date, time, and a piece-good/bad tag into a structured DB so the operator can pull the file once a week and open it in Excel.
This reference covers the full path: UDT design, DB layout, the SFCs needed to read the real-time clock and copy structured records, ring-buffer logic to handle 100+ events/day, the MMC write-cycle budget, and the export workflow from STEP 7 to a spreadsheet.
DATE_AND_TIME (DT) is 8 bytes, plus a quality byte and a small header, each event costs ~10–12 bytes. 100 events/day × 7 days = 28 KB just for data — too much for the work memory. Plan for a ring buffer of 100–300 events (about 3 KB) and accept that you will overwrite older records when the buffer fills, or upgrade the MMC to a larger size and accept the write-cycle wear.Prerequisites
| Item | Specification |
|---|---|
| CPU | 6ES7 313-5BF03-0AB0 (CPU 313C), firmware V2.6 or higher recommended |
| Work memory | 32 KB (code + data) |
| Load memory | MMC up to 8 MB (order numbers 6ES7 953-1Lx00-0AA0, size x = 0/1/2 for 64 KB/128 KB/512 KB; L = M for 2 MB; L = J for 4 MB; L = K for 8 MB) |
| Retentive area | Configurable; non-retentive by default for the archive DB unless explicitly marked |
| Engineering tool | STEP 7 V5.5 + SP2 or STEP 7 V5.6 (TIA Portal V13+ supports the same 300 family via GSD import) |
| Required SFCs | SFC 0 (SET_CLK), SFC 1 (READ_CLK), SFC 20 (BLKMOV), SFC 22 (CREAT_DB) — see Siemens Entry ID 21222026 — Reading and setting the time on S7-300/400 |
DATE_AND_TIME Data Format on S7-300
The DT type is a BCD-encoded 8-byte structure. Each event record needs to store this in a known layout so it can be parsed later:
| Byte | Field | Range (BCD) | Comment |
|---|---|---|---|
| 0 | Year | 90–89 (1990–2089) | Read DT.YEAR as BCD, add 1900/2000 offset in Excel |
| 1 | Month | 01–12 | |
| 2 | Day | 01–31 | |
| 3 | Hour | 00–23 | |
| 4 | Minute | 00–59 | |
| 5 | Second | 00–59 | |
| 6 | Milliseconds (3 BCD digits, 0–999) | 000–999 | High nibble = hundreds |
| 7 | Milliseconds (low 2 digits) + weekday (1–7, Sun=1) | 00–99 ms, 1–7 day | Low nibble of high byte = weekday |
Because the PLC stores values in BCD and Excel has no native BCD type, the simplest export is to declare the DT field as a DATE_AND_TIME variable in the DB and read it in STEP 7 as DT in human-readable form, or split the DT into individual BYTE fields (year, month, day, hour, minute, second) using a UDT and convert BCD → INT in the spreadsheet.
Step 1 — Define a UDT for One Event Record
Create a User-Defined Data Type UDT_ArchiveEntry in the STEP 7 program editor. This keeps the DB layout self-documenting and lets you resize the ring buffer by editing the UDT array length only.
TYPE UDT_ArchiveEntry
STRUCT
EventYear : BYTE; // BCD 90..89
EventMonth : BYTE; // BCD 01..12
EventDay : BYTE; // BCD 01..31
EventHour : BYTE; // BCD 00..23
EventMinute : BYTE; // BCD 00..59
EventSecond : BYTE; // BCD 00..59
EventMs : WORD; // 16 bits, 0..999 ms, BCD-encoded
QualityBit : BOOL; // 0 = bad piece, 1 = good piece
Spare : BYTE; // alignment, set to 0
END_STRUCT;
END_TYPE
Each entry costs exactly 10 bytes. With a 100-entry buffer the data footprint is 1,000 bytes; with 300 entries it is 3,000 bytes. Both are well within the 313C's work memory budget for data blocks (16 KB of the 32 KB is reserved for DBs after FB/FC/OB code is loaded).
Step 2 — Build the Archive DB
Create DB_Archive with three sections: header, ring buffer, and overflow counter.
DATA_BLOCK DB_Archive
STRUCT
Header : STRUCT
MaxEntries : INT := 300; // ring length
WritePointer : INT := 0; // next slot to write, 0..MaxEntries-1
EntryCount : INT := 0; // total events captured (saturating)
OverflowCnt : INT := 0; // how many times we wrapped
Magic : WORD := 16#4141; // "AA" — sanity marker
END_STRUCT;
Buffer : ARRAY[1..300] OF UDT_ArchiveEntry;
END_STRUCT;
END_DATA_BLOCK
Header size: 10 bytes. Buffer size: 3,000 bytes. Total DB: 3,010 bytes. Set the DB attribute Non-retain so a power-cycle clears the buffer; or, if you want the last 7 days to survive an outage, set the entire DB to Retain using the STEP 7 Block Properties → Attributes tab. The 313C supports up to 8 retentive DBs depending on the configured retentive area in HW Config → CPU → Retentive Memory.
Step 3 — Read the System Clock with SFC 1
SFC 1 (READ_CLK) returns the current PLC date/time as a DT in a target area. Call it from OB 1 (cyclic) on every scan, or call it only when an event is detected. Reference: Siemens Entry ID 21222026 — Reading and Setting the Time on S7-300/400.
// STL — call only on event edge to minimize overhead
CALL SFC 1
RET_VAL := MW 100 // error code, 0 = OK
CDT := P#DB_Archive.DBX 0.0 BYTE 8
// ^ stores DT into the start of the first buffer slot
// (overwrite later; this is just a scratch read)
SFC 1 RET_VAL error codes per Siemens TIA Portal — CREA_DB / SFC reference:
-
W#16#0000— no error -
W#16#8080— clock not set (CPU in cold start, no battery on 313C internal clock) -
W#16#80A0— error reading internal clock (hardware fault, rare)
RET_VAL and warn the user if it is non-zero.Step 4 — Edge Detection and Record Write
Use a positive edge flag to capture one record per event. A complete FC for the archive task follows.
FUNCTION FC 100 : VOID
VAR_TEMP
dtScratch : DATE_AND_TIME;
sfcRetVal : WORD;
ptr : DWORD;
END_VAR
BEGIN
// 1. Edge detect: M20.0 rising
A M 20.0;
FP M 20.1; // M20.1 = edge memory bit
JCN endFC; // skip if no rising edge
// 2. Read clock into scratch DT
CALL SFC 1
RET_VAL := sfcRetVal
CDT := dtScratch;
L sfcRetVal;
L W#16#0;
<>I ;
JCN endFC; // abort if clock read failed
// 3. Compute next write slot in DB_Archive.Buffer[WritePointer]
L DB_Archive.Header.WritePointer; // current slot 0..299
L 1;
+I ;
L DB_Archive.Header.MaxEntries;
MOD ; // wrap 300 -> 0
T DB_Archive.Header.NextPointer; // local temp
// 4. Move scratch DT into buffer slot using SFC 20 (BLKMOV)
L DB_Archive.Header.WritePointer;
L 10; // size of UDT_ArchiveEntry
*D ;
SLD 3; // convert to bit pointer
L P#DB_Archive.Buffer[1];
+D ;
T ptr;
CALL SFC 20
SRCBLK := dtScratch
RET_VAL := sfcRetVal
DSTBLK := ptr;
// 5. Write quality bit
A M 20.2; // 0 = bad piece, 1 = good piece
= DB_Archive.Buffer[...].QualityBit;
// 6. Update header counters
L DB_Archive.Header.EntryCount;
L 1;
+I ;
T DB_Archive.Header.EntryCount;
L DB_Archive.Header.WritePointer;
L 1;
+I ;
L DB_Archive.Header.MaxEntries;
MOD ;
T DB_Archive.Header.WritePointer;
// 7. Detect wrap to bump OverflowCnt
L DB_Archive.Header.WritePointer;
L 0;
==I ;
JCN endFC;
L DB_Archive.Header.OverflowCnt;
L 1;
+I ;
T DB_Archive.Header.OverflowCnt;
endFC: NOP 0;
END_FUNCTION
Reference for SFC 20 BLKMOV: Siemens Entry ID 1215174 — SFC 20 BLKMOV on S7-300/400.
Step 5 — Alternative: Cyclic Logging in OB 35
If the source machine's events are not clean rising edges (for example a slow analog threshold that toggles), or if the operator wants a continuous trace, switch from event-driven to cyclic logging in OB 35. The 313C defaults OB 35 to a 100 ms call period; you can change this in HW Config → CPU → Cyclic Interrupts to 1,000 ms (1 second) for an archive of one row per second.
// OB35 example — write one entry per cycle
CALL SFC 1
RET_VAL := MW 102
CDT := #dtNow;
// build UDT bytes from #dtNow using TAW / CAD logic
// then BLKMOV into Buffer[WritePointer] as in Step 4
At 1 Hz, 86,400 records/day would fill a 300-slot ring buffer in 3 seconds, so set OB 35 to a longer period (e.g., 60 s = 1,440 records/day) or increase the buffer to several thousand entries — but the latter quickly exhausts the 313C's 16 KB of DB work memory. The event-driven approach in Step 4 is the better fit for the 100 events/day scenario.
MMC Write-Cycle Budget
Two memory tiers matter on the 313C:
- Work memory (volatile): 32 KB. Holds the running DB. The DB is rewritten in RAM on every event — no wear.
-
Load memory (MMC, non-volatile): Up to 8 MB. The DB is paged to MMC only when you call
Save to Memory Cardor on a warm restart dump. Wear depends on how often you force a download/save.
Standard Siemens MMCs for the 300 family are rated for 100,000 to 1,000,000 write cycles per sector (see MMC datasheets — 6ES7 953-1Lxxx). For a once-a-week manual download, the wear is negligible. The MMC should be replaced if SF + BATF LEDs light together, which indicates a memory card fault.
CREAT_DB) calls or as direct writes triggered by every OB 1 scan — that re-creates the DB on the MMC repeatedly and consumes write cycles far faster than useful work. Use event-driven SFC 1 + SFC 20 in work-memory DB only; the MMC is touched only on operator-initiated download. See Siemens TIA Portal — CREA_DB documentation for the system function's behavior.Step 6 — Export the DB to Excel
- In STEP 7 (SIMATIC Manager), right-click
DB_Archive→ Monitor/Modify and confirm the buffer fills as expected. - With the CPU in STOP or online, select PLC → Upload Station to PG to copy
DB_Archiveto your project. - Open Options → Charts: DB Archive or use the Save As option in the data view, then export to
.csv. For larger dumps use the STEP 7 DataBlock Export add-on or the open-source libnodave / Snap7 libraries (free, no licensing) to script the read in Python and write directly to.xlsx. - In Excel, run Text-to-Columns on the BCD byte columns, then use a formula such as
=HEX2DEC(MID(A2,1,2))+1900to convert BCD year to a 4-digit integer. Convert milliseconds with=TIMEVALUE(MID(A2,7,2)":"&MID(A2,9,2))after splitting the WORD.
For unattended retrieval, an Ethernet CP 343-1 Lean (6GK7 343-1CX10-0XE0) can push the DB over FTP or a custom TCP frame once a week when the operator's laptop connects; this is preferred to swapping the MMC, which requires a CPU stop and risks configuration drift.
Verification Checklist
-
Clock sanity: Force
SET_CLKvia SFC 0 in OB 100 with the current time; verify the time persists across a power cycle (CPU 313C retains the clock only with the optional battery module 6ES7 311-1CA00-0AA0). -
Edge capture: Toggle
M20.0ten times manually in Monitor/Modify; confirmDB_Archive.Header.EntryCountincrements to 10 and the first 10 slots ofBuffercontain DT values. -
Ring wrap: Set
MaxEntries := 5temporarily and trigger 10 events; confirmOverflowCnt = 1andWritePointer = 0. -
Quality bit: Toggle
M20.2before each test event and confirm the storedQualityBitmatches the live state at the time of edge. - Export round-trip: Upload the DB, open in Excel, confirm a clean table with 100 rows for 100 trigger events and that the DT decode matches the wall clock within ±1 s.
Troubleshooting Matrix
| Symptom | Likely Root Cause | Fix |
|---|---|---|
| All events have timestamp 01.01.1994 00:00:00 | CPU 313C has no battery; SFC 1 returns default after power-up | Install battery 6ES7 311-1CA00-0AA0, add SFC 0 in OB 100 to set time from a master (HMI/CP), or accept cold-start zero as data quality marker |
RET_VAL = W#16#8080 |
Clock not set on CPU | Same as above; never ignore this return |
| Buffer fills but timestamps are identical to the second | OB 35 period too short or SFC 1 called only once outside edge | Move SFC 1 call into the same FC that detects the edge, or increase OB 35 period to 60 s |
| SF LED on + MMC fault at startup | MMC exhausted write cycles or removed while CPU was writing | Replace MMC; never hot-swap the card; use a 4–8 MB MMC to spread wear |
| DB upload to PG shows 0x00 in all slots | DB marked non-retentive and CPU power cycled | Set Retain in block properties or accept that the buffer is volatile |
| Pointer arithmetic faults (SF + OB 121 stop) | WritePointer exceeded MaxEntries before MOD | Wrap WritePointer with MOD MaxEntries before the BLKMOV call, not after |
| Excel export shows garbled characters in time column | Reading BCD bytes as ASCII text | Convert BCD → INT with HEX2DEC + offset, or split the DT in STEP 7 into individual byte fields before export |
Field-Proven Caveats
1. Do not run the archive inside OB 1 unconditionally. Even with a small DB, calling SFC 1 + SFC 20 every scan wastes scan time. Trigger only on the event edge.
2. Time zones and DST. The 313C clock has no concept of DST; if the plant observes daylight saving, either disable automatic DST on whatever master you sync to, or store an explicit UTC offset byte in each record.
3. Retentive memory budget. The 313C allows up to 8 KB of retentive data; if other parts of the program already use that, the archive DB may not fit. Drop MaxEntries or use a non-retentive DB and download the buffer at every shift change.
4. Multi-shift operations. If the machine runs unattended for more than one shift, increase the buffer to ~500 entries; at 100 events/day, 5 days fit in 1,000 bytes and the operator still has 5× the memory headroom of a 100-entry buffer.
5. AR_SEND is not for S7-300. The AR_SEND block targets S7-400 only. S7-300 users must rely on SFC 1 + SFC 20 + manual upload as documented above.
FAQ
How many events can a CPU 313C buffer before wrapping?
With a 10-byte UDT and 16 KB of work memory for DBs, the practical maximum is 1,500–1,600 entries. For a 100 events/day machine, 300 entries cover 3 days and fit in 3 KB; expand to 500 entries (5 KB) for a full working week without wrap.
Do I need a battery module to keep timestamps correct?
Yes — the 6ES7 311-1CA00-0AA0 battery is required if you want the real-time clock to survive a power loss. Without it, SFC 1 returns the default date 01.01.1994 00:00:00 after every cold start and the timestamps become useless. Alternatively, sync the clock from a connected HMI or CP 343-1 in OB 100 on every restart.
Can I write the archive directly to the MMC to avoid filling work memory?
No. The 313C runs the user program only from work memory; DBs are stored in work memory, not on the MMC, except during a save or download. Continuous writing to the MMC is not supported and would wear the card out in days. Use work-memory DBs and only touch the MMC on operator-initiated upload or project save.
What SFC returns the current date and time?
SFC 1 (READ_CLK) returns the CPU's real-time clock as an 8-byte DATE_AND_TIME value. Pair it with SFC 0 (SET_CLK) to set the clock and SFC 20 (BLKMOV) to copy the DT into your archive slot. See Siemens Entry ID 21222026.
Can the S7-300 archive a DB automatically and email it?
No — S7-300 has no native email client. The only options are: weekly manual upload via MPI/Profibus/Ethernet CP, swapping the MMC and reading it on a PC with a prommer, or adding a CP 343-1 IT (6GK7 343-1GX11-0XE0) with a custom TCP/FTP script. For truly unattended archiving, upgrade to an S7-1500 with web server or to a WinCC Runtime station.