Archiving Event Data in S7-300 DB Blocks with DATE_AND_TIME

David Krause13 min read
S7-300SiemensTutorial / How-to
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

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.

Constraint check first. The 313C is a compact CPU with 32 KB of work memory. A full 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)
The CPU 313C has no battery-backed real-time clock when running from MMC. The clock starts at 01.01.1994 00:00:00 after every power-up unless an external time master (SFC 0 SET_CLK, NTP via CP, or HMI time sync) pushes the current time. Always check the 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 Card or 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.

Do not implement the archive as continuous SFC 22 (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

  1. In STEP 7 (SIMATIC Manager), right-click DB_ArchiveMonitor/Modify and confirm the buffer fills as expected.
  2. With the CPU in STOP or online, select PLC → Upload Station to PG to copy DB_Archive to your project.
  3. 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.
  4. In Excel, run Text-to-Columns on the BCD byte columns, then use a formula such as =HEX2DEC(MID(A2,1,2))+1900 to 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_CLK via 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.0 ten times manually in Monitor/Modify; confirm DB_Archive.Header.EntryCount increments to 10 and the first 10 slots of Buffer contain DT values.
  • Ring wrap: Set MaxEntries := 5 temporarily and trigger 10 events; confirm OverflowCnt = 1 and WritePointer = 0.
  • Quality bit: Toggle M20.2 before each test event and confirm the stored QualityBit matches 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.

Back to blog