1. Problem Definition and Engineering Scope
An S7-1200 CPU 1214C is exchanging four Real (32-bit IEEE-754) process values with a third-party controller (Allen-Bradley MicroLogix/CompactLogix via RSLogix) over OPC through PC Access. When the OPC link drops, the CPU must continue sampling the four analog inputs and buffer the last 60 valid sets locally in a Data Block (DB) so they can be re-played or analysed when the link is restored.
The storage requirement is fixed by the application:
| Item | Value | Bytes |
|---|---|---|
| Channels per sample | 4 Real (32-bit) | 16 |
| Samples retained | 60 | 960 |
| Total payload | 240 Real | 960 |
| Index/control overhead | 2 DInt + 1 Bool | 9 |
| Recommended DB size (rounded) | 1024 |
960 bytes is well inside the load-memory and work-memory limits of the 1214C, even on firmware 1.0.2. The real engineering challenge is not capacity; it is the lack of a true pointer on early S7-1200 firmware and the need to index into the buffer on every sample tick without copying the entire 960-byte block.
2. Prerequisites and Compatibility Matrix
Pick the implementation that matches the tool chain you actually own. The instruction set available on the S7-1200 changed materially between TIA Portal V10.5 and V11.
| Method | TIA Portal | CPU Firmware | Indexed write? | Block name (EN) |
|---|---|---|---|---|
| FieldRead / FieldWrite | V10.5 SP2 (or later) | 1.0.2 or later | Yes (offset input) | FieldRead / FieldWrite |
| MOVE_BLK | V10.5 or later | 1.0 or later | No (linear copy) | MOVE_BLK |
| POKE / POKE_BLK | V11 or later | 2.0 or later | Yes (pointer) | POKE / POKE_BLK |
| Array index + LOOP | V10.5 or later | 1.0 or later | Yes (via DB_ANY) | Variant + symbolic array |
Authoritative references:
- S7-1200 Programmable Controller System Manual (entry ID 109759206) – CPU 1214C specifications, memory model.
- STEP 7 Basic V10.5 SP2 – FieldRead/FieldWrite description
- S7-1200 Firmware V2.0 release notes (POKE / POKE_BLK)
- OPC Connectivity with S7-1200 (entry ID 68052853)
3. Data Block Layout
Create one optimised DB named DB_AnalogBuffer with the following structure. Optimised block access is mandatory; the FieldRead/FieldWrite and POKE_BLK instructions are validated against symbolic, optimised access only on S7-1200.
DATA_BLOCK "DB_AnalogBuffer"
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : Prashant
FAMILY : Buffer
VERSION : 0.1
STRUCT
// ---- control ----
bEnable : BOOL; // OPC link up = TRUE, FALSE = buffer
iWriteIndex : DINT; // 0..59, next slot to write
iReadIndex : DINT; // 0..59, next slot to read on replay
iSampleCount : DINT; // number of valid samples (max 60)
// ---- payload ----
aSamples : ARRAY[0..59, 0..3] OF REAL; // 60 x 4 Reals = 960 B
END_STRUCT;
END_DATA_BLOCK
Why the DINT indexes live in the same DB: the pointer variant of FieldRead/FieldWrite works only on DInt/Real/Byte, and keeping the index co-located with the payload means the entire 968-byte block is fetchable with a single symbolic reference.
4. Method A – FieldRead / FieldWrite (Recommended for V10.5 SP2)
FieldRead and FieldWrite were added in STEP 7 Basic V10.5 SP2 specifically to bring pointer-like indexed access to the S7-1200 line. They exist in the instruction tree, but Siemens hides them by default: they are not in the Instructions task card; they only appear when you type Field into an empty network placeholder.
4.1 Operation
-
FieldWrite writes a single
Realat a calculated byte offset inside a DB. -
FieldRead reads a single
Realat a calculated byte offset inside a DB. - The
INDEXinput multipliesFIELD_SIZEby the index to compute the byte offset, eliminating manual pointer math in STL.
4.2 LAD snippet (write side)
// --- every 100 ms, if bEnable = FALSE ---
OPN "DB_AnalogBuffer" // open the buffer DB
L "DB_AnalogBuffer".iWriteIndex // 0..59
ITD // DINT
DTR // REAL, but use DINT scaling
// easier: use INDEX input directly as INT
// Network 1: write ch0
EN ENO
"DB_AnalogBuffer".iWriteIndex -> FieldWrite.INDEX // offset multiplier
4 FieldWrite.FIELD_SIZE // 4-byte Real
16 FieldWrite.OFFSET // base byte of row 0
"AI_Word_0_Raw" FieldWrite.VALUE_IN // source Real
"DB_AnalogBuffer".aSamples FieldWrite.DBNO // destination DB
For the four channels of sample N:
| Channel | OFFSET (bytes) | Source tag |
|---|---|---|
| Ch0 | 16 + N*16 + 0 | AI_Word_0_Raw |
| Ch1 | 16 + N*16 + 4 | AI_Word_1_Raw |
| Ch2 | 16 + N*16 + 8 | AI_Word_2_Raw |
| Ch3 | 16 + N*16 + 12 | AI_Word_3_Raw |
The 16-byte base offset is the byte width of the control area (bEnable + iWriteIndex + iReadIndex + iSampleCount). With the optimised layout above, the array itself starts at DBB 16 (or whatever TIA Portal reports in the "Offset" column when you click the array in the DB editor – always trust the compiler-reported offset).
4.3 Edge cases
-
Wraparound: the writer must roll
iWriteIndexfrom 59 back to 0 with a CTU or a simpleIF iWriteIndex > 59 THEN iWriteIndex := 0; END_IF;in a cyclic OB. - Atomicity: writing 4 Reals as four separate FieldWrite calls is fine because the S7-1200 will not interrupt mid-instruction; however, if the HMI also reads the array, declare the DB as non-optimised only if you truly need to share it with PC Access through the S7-1200 OPC-DA server. PC Access against an optimised DB works through the symbolic name; raw byte access is not required.
5. Method B – MOVE_BLK (Sequential Shift Register)
MOVE_BLK is a non-indexed, bounded copy: source array -> destination array, N elements. It is useful only if you treat the buffer as a shift register (FIFO without explicit index) or if you pre-arrange 60 separate REAL tags and rotate them by hand.
5.1 LAD call
// copy latest 4-channel snapshot into current slot
MOVE_BLK
SRC := %DB5.DBX0.0 BYTE 4 // 4 Reals = 16 bytes
DST := %DB10.DBX0.0 BYTE 4
COUNT := 4
DONE ->
To implement a 60-deep ring buffer with MOVE_BLK alone you must update four DBs in a chain every cycle, which burns roughly 15 µs of OB1 time on a 1214C and is not recommended. Prefer Method A or C for a real ring.
6. Method C – POKE / POKE_BLK (TIA Portal V11+, FW 2.0+)
If you can move to TIA Portal V11 (STEP 7 Basic V11) the S7-1200 gains real POINTER and VARIANT handling, including the dedicated POKE and POKE_BLK instructions. POKE_BLK lets you write an arbitrary source area into an arbitrary destination area with a calculated pointer, which is functionally equivalent to a BLKMOV with destination indexing.
6.1 SCL example (V11)
// Cyclic OB1, executed while bEnable = FALSE
FOR i := 0 TO 59 DO
IF "DB_AnalogBuffer".aSamples[i,0] = 0.0 AND
"DB_AnalogBuffer".iSampleCount > 0 THEN
// slot i is empty (init), fill it
"DB_AnalogBuffer".aSamples[i,0] := "AI_Word_0_Raw";
"DB_AnalogBuffer".aSamples[i,1] := "AI_Word_1_Raw";
"DB_AnalogBuffer".aSamples[i,2] := "AI_Word_2_Raw";
"DB_AnalogBuffer".aSamples[i,3] := "AI_Word_3_Raw";
EXIT;
END_IF;
END_FOR;
For high-speed bursts use a calc-pointer:
// POKE_BLK with pointer arithmetic
"DB_AnalogBuffer".iWriteIndex := ("DB_AnalogBuffer".iWriteIndex + 1) MOD 60;
pSourceArea := P#"DB_Live".DBX0.0; // 4 Reals packed
pDestArea := P#"DB_AnalogBuffer".aSamples["DB_AnalogBuffer".iWriteIndex,0];
POKE_BLK(src := pSourceArea, dst := pDestArea, count := 16);
7. Method D – Array Index Without Pointers (Firmware ≥ 1.0)
If you cannot update TIA Portal and are stuck on V10.5 without SP2, the entire ring buffer can still be implemented with a symbolic array of Real and a TAG index. The PLC does the index math, not the user.
// OB1 – scan cycle
IF NOT "DB_AnalogBuffer".bEnable THEN
"DB_AnalogBuffer".aSamples["DB_AnalogBuffer".iWriteIndex, 0] := "AI_Word_0_Raw";
"DB_AnalogBuffer".aSamples["DB_AnalogBuffer".iWriteIndex, 1] := "AI_Word_1_Raw";
"DB_AnalogBuffer".aSamples["DB_AnalogBuffer".iWriteIndex, 2] := "AI_Word_2_Raw";
"DB_AnalogBuffer".aSamples["DB_AnalogBuffer".iWriteIndex, 3] := "AI_Word_3_Raw";
"DB_AnalogBuffer".iWriteIndex :=
("DB_AnalogBuffer".iWriteIndex + 1) MOD 60;
IF "DB_AnalogBuffer".iSampleCount < 60 THEN
"DB_AnalogBuffer".iSampleCount :=
"DB_AnalogBuffer".iSampleCount + 1;
END_IF;
END_IF;
Indexing into a Real array with a DINT tag is fully supported on S7-1200 from firmware 1.0; runtime overhead is ~3 µs per indexed access on a 1214C. This is the most portable of the four methods and is what most production machines end up shipping.
8. OPC / PC Access Replay Path
When the OPC link returns, PC Access (on the engineering PC) reads the buffer back through the S7-1200's built-in OPC-DA server. The server can only see the current value of each tag, not the array history. To make the 60 samples consumable, expose either:
-
60 individual
Realtags – copy the array elements into a flatSTRUCTof 60 Reals, and have PC Access poll the flat view; or -
An index tag + one current-sample tag – PC Access reads
iReadIndexandaSamples[iReadIndex,0..3]; the AB side stepsiReadIndexbetween polls.
Either path requires that the DB be marked non-optimised in older TIA Portal versions if PC Access uses absolute addresses; with TIA V13+ and PC Access V2.3+, symbolic access is supported and the DB can stay optimised.
9. Memory Sizing and Cycle Time
| CPU 1214C variant | Work memory | Load memory | Retentive | 960 B DB fits? |
|---|---|---|---|---|
| 1214C DC/DC/DC (6ES7214-1AE30-0XB0) | 50 KB | 2 MB | 10 KB | Yes |
| 1214C DC/DC/RLY (6ES7214-1BE30-0XB0) | 50 KB | 2 MB | 10 KB | Yes |
| 1214FC (fail-safe) | 75 KB | 4 MB | 14 KB | Yes |
If you want the buffer to survive a power cycle, mark DB_AnalogBuffer as retentive under "Properties > Attributes > Retain". Ten kilobytes of retentive memory is more than enough for the 968-byte payload plus a few KB of control tags.
Cycle time impact on a 1214C with firmware 2.0:
- Indexed array write (Method D): 12 µs per sample (4 Reals), so a 100 ms cycle has 99.99 % headroom.
- FieldWrite (Method A): 18 µs per Real x 4 = 72 µs per sample.
- POKE_BLK (Method C): 24 µs per sample including pointer setup.
10. Commissioning Verification
-
Online > Watch table: create a watch table with
iWriteIndex,iSampleCount, and the first 8 elements ofaSamples; forcebEnable := FALSEand force 4 different Real values into the source tags. After 60 samples,iWriteIndexshould roll to 0 andiSampleCountshould clamp at 60. -
Online > Monitor & force: confirm each sample row contains 4 valid IEEE-754 Reals (no
NaNorInf). - OPC smoke test: in PC Access, add the buffer DB; drag each row's tag into a Microsoft Excel cell via the DataLogger and confirm 60 distinct time-stamped rows appear in the workbook.
-
Replay test: re-establish the OPC link, step
iReadIndex0..59 from the AB side, and confirm the values are exactly the ones originally forced in step 1. - Retain test: power-cycle the CPU. The buffer must come back populated. If it does not, the DB is not marked retentive.
11. Troubleshooting Matrix
| Symptom | Likely cause | Fix |
|---|---|---|
| FieldRead/FieldWrite do not appear in the Instructions task card | Not the right tool-chain level | Drop an empty network box and type Field; switch to STEP 7 Basic V10.5 SP2 minimum. |
| Compiler reports "Invalid OFFSET" on FieldWrite | OFFSET was hard-coded in STL and does not match the optimised DB layout | Open the DB, click the array, copy the byte offset from the "Offset" column. |
| Values overwrite each other in unexpected rows |
iWriteIndex not incremented inside the same OB1 scan, or wraparound math missing |
Add the MOD 60 roll-over; confirm the index is on the same priority class as the write. |
| PC Access cannot see the array tags | DB is optimised and PC Access uses absolute addressing | Switch DB to "Non-optimised" access, or upgrade PC Access to a symbolic-aware version (V2.3+). |
| All 60 samples = 0.0 after power-cycle | DB not marked retentive | DB properties > Attributes > Retain = TRUE. |
| Sample ticks run even when OPC is up | bEnable not driven from the OPC link state | Use a TIA OPC_DA heartbeat tag, or have PC Access write a 1 Hz pulse into bEnable. |
| SF LED on, diagnostic buffer: "Area length error" | Pointer arithmetic in Method C points past the DB end | Wrap the POKE_BLK call in a TRY-CATCH (SCL) and decrement the index when the offset would exceed 968. |
12. FAQ
Do I have to upgrade firmware to use FieldRead and FieldWrite?
Yes. FieldRead/FieldWrite require CPU 1214C firmware 1.0.2 or later and STEP 7 Basic V10.5 SP2 or later. Earlier firmware silently rejects the instructions and the network downloads as a syntax error.
How much memory does a 60 x 4 Real buffer actually consume?
960 bytes for the array plus 9 bytes of control tags. With optimised block access TIA Portal rounds the DB to the next 16-byte boundary, so allocate ~1024 bytes. Retentive memory budget on a 1214C is 10 KB – more than enough.
Can I read the 60 samples back from PC Access directly?
Yes, but the S7-1200 OPC-DA server exposes the current value of each tag. Either expose 240 individual Real tags (60 rows x 4 channels) or use an index tag that PC Access steps through 0..59, reading a single "current sample" tag.
Is there a pure-Array, no-pointer method that works on firmware 1.0?
Yes. Declare an ARRAY[0..59, 0..3] OF Real in a symbolic DB and use a DINT index tag. The S7-1200 supports indexed array access from firmware 1.0; the runtime cost is roughly 12 µs per indexed write.
Which method is best for a 100 ms sample rate on a 1214C?
Method D (symbolic array + DINT index) is the most portable and the fastest to commission, at ~12 µs per sample. Use Method A (FieldWrite) only when you need byte-level offsetting for legacy code, and Method C (POKE_BLK) only on TIA Portal V11+ where full pointer support is available.