S7-1200 MOVE_BLK: Indirect Addressing IW to Word Array

David Krause11 min read
SiemensTIA PortalTutorial / 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

Overview

Moving a contiguous block of process input words (for example %IW100 through %IW109) into a WORD array is a recurring requirement on S7-1200 and S7-1500 controllers programmed in TIA Portal. Typical applications include scan-time logging, conditional recipe comparison, diagnostic snapshots captured at the moment of a fault, and indexing data structures that a downstream function block consumes by index. The challenge is that IW addresses are absolute input area operands and cannot be indexed symbolically, so any "copy 10 (or 43) words in one operation" must be expressed through a block-move instruction, an AT-view overlay, or a small SCL loop.

This reference covers four engineering-proven methods for S7-1200 MOVE_BLK indirect addressing:

  1. Individual MOVE calls (works on every CPU firmware).
  2. MOVE_BLK (formerly BLKMOV) - one-call bulk copy from a pointer to an ARRAY.
  3. SCL FOR loop using PE/WP-style indexed input access.
  4. AT-view overlay that reinterprets the I-area as an ARRAY[0..n] OF WORD.

Each method has trade-offs in legibility, runtime, scan-time impact, and minimum firmware level. The decision matrix at the end of this article lets you select the right approach based on controller firmware, array size, and update rate.

Firmware compatibility: MOVE_BLK is available from S7-1200 firmware V4.0 onward. CPUs at V3.0 must use the legacy BLKMOV instruction from the "Extended instructions" palette, or fall back to a ladder MOVE rung for every word. On S7-1500, MOVE_BLK is available in all standard firmware versions and supports VARIANT inputs as of TIA Portal V15.

Prerequisites

  • TIA Portal V15.1 or later (V16+ recommended for VARIANT-based block-move).
  • S7-1200 CPU with firmware 4.0 or higher (any S7-1500 also acceptable).
  • SCL compiler licence enabled (standard on S7-1200 from FW 4.2; always standard on S7-1500).
  • A configured DB containing an ARRAY[1..n] OF WORD target, where n matches the number of input words (10 in the question, 43 in the follow-up).
  • Input modules wired to IW100 through IW(99+n) in the device configuration. Unwired addresses return 16#0000, not an error.
  • Knowledge of how TIA Portal converts classic IW addresses to the new fully-qualified form: %IW100. The compiler always interprets bare IW100 as the bit/byte/word/dword offset 100 in the input process image.

Input Word Addressing Fundamentals

The process image of inputs (PII) is a byte-addressed memory region updated at the start of every OB1 cycle. Word alignment requires even offsets, so %IW100 occupies byte 100 and byte 101. The full block %IW100..%IW109 therefore spans bytes 100 through 119 and represents 20 bytes of input status.

When you attempt to assign to a typed ARRAY element, the compiler enforces element-by-element copy. Direct slice assignment such as MyArray := %IW100 is rejected because the source is a scalar WORD and the destination is an array. This is the core reason that block-move or loop constructs are required.

Address Table

Classic operand Fully-qualified form Byte offset Size
IW100 %IW100 100-101 WORD
IW102 %IW102 102-103 WORD
IW104 %IW104 104-105 WORD
... ... ... ...
IW108 %IW108 108-109 WORD
Total - 100-119 10 WORD = 20 bytes

Method 1: Individual MOVE Instructions (Ladder / FBD)

The simplest portable technique is one MOVE per word. It compiles on every CPU firmware and is trivial to debug in the watch table. The drawback is rung count: 10 rungs for a 10-word block, 43 rungs for a 43-word block.

  1. Open the OB1 or FC/FB that owns the snapshot.
  2. Insert an empty network for each input word.
  3. Drop a MOVE box; wire %IW100 to IN and "MyDB".WordArray[1] to OUT1.
  4. Repeat for %IW102 through %IW108, mapping to indices 2 through 10.

This approach is recommended only for blocks of fewer than 8 words. Beyond that, the editor becomes unwieldy and a single renaming task touches every rung.

Method 2: MOVE_BLK Block Move (TIA V15+)

MOVE_BLK copies a contiguous source range to a contiguous destination range. On S7-1200 firmware 4.0+ and S7-1500 it accepts a pointer for the source and a typed ARRAY tag for the destination, eliminating the rung-per-word problem.

Parameter Reference

Parameter Direction Data type Meaning
EN Input BOOL Enable - normally TRUE.
IN Input POINTER / VARIANT Source area pointer to %IW100.
COUNT Input UINT Number of elements to copy (10 or 43).
OUT Output ARRAY[*] OF WORD Destination array, indexed from the lower bound.
ENO Output BOOL Set FALSE on pointer fault.

Ladder Example

      MOVE_BLK
EN    |
--| |---+      IN := P#I 100.0 WORD 10
      |       OUT := "DB_Inputs".WordArray
      |     COUNT := 10
      |       ENO--

FBD Example

  1. Insert Instructions > Move operations > MOVE_BLK.
  2. At IN, type the absolute pointer P#I 100.0 WORD 10. The pointer form is: P#<area> <byte.bit> <data type> <count>. Area I = inputs, Q = outputs, M = bit memory.
  3. At OUT, drag the array tag "DB_Inputs".WordArray.
  4. At COUNT, enter the literal 10 or a tag iCount of type UINT.
Pointer syntax: P#I 100.0 WORD 10 means "starting at input byte 100 bit 0, copy 10 WORD elements (20 bytes).". A mismatch between COUNT and the actual destination array length produces an access fault at runtime; check ENO in the watch table.

SCL Equivalent

// SCL - TIA Portal V15+
"DB_Inputs".WordArray := #dummyTarget;
MOVE_BLK(
    IN   := P#I 100.0 WORD 10,
    COUNT := 10,
    OUT  := "DB_Inputs".WordArray,
    ENO  => #blkErr
);

Method 3: SCL FOR Loop with Indexed Access

For symbolic access to each word with a single block of source code, an SCL FOR loop is the cleanest expression. On S7-1200 you cannot index an I-area symbol directly, so the loop walks a separate pointer increment and writes to the array index.

Pattern A - Loop + MOVE per iteration

FUNCTION_BLOCK "FB_InputSnapshot"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT
      iCount : UINT := 10;
   END_VAR
   VAR_IN_OUT
      ioArray : ARRAY[1..50] OF WORD;
   END_VAR
   VAR
      i : INT;
   END_VAR
BEGIN
   // Copy iCount input words starting at %IW100 into ioArray[1..iCount]
   FOR i := 1 TO TO_INT(iCount) DO
      CASE i OF
         1  : ioArray[1]  := "IW100";
         2  : ioArray[2]  := "IW102";
         3  : ioArray[3]  := "IW104";
         4  : ioArray[4]  := "IW106";
         5  : ioArray[5]  := "IW108";
         // extend to 43 entries as needed
      END_CASE;
   END_FOR;
END_FUNCTION_BLOCK

Pattern B - PEEK instruction (S7-1500 only)

On S7-1500 the PEEK instruction reads a byte from the input area given a WORD offset. Wrap it in a loop for indirect reads:

FOR i := 0 TO 9 DO
    // PEEK uses BYTE index; IW100 = bytes 100..101
    ioArray[i+1] := WORD_TO_BLOCK_DB_PEEK(...); // placeholder syntax
END_FOR;

For production code, prefer the PEEK/POKE helpers in the Extended instructions > Address palette. On S7-1200 these helpers are not available, which is why the AT-view method (Method 4) is usually the right answer there.

Method 4: AT-View Overlay on the Input Area (Recommended for S7-1200)

The AT-view is the most efficient and elegant solution on S7-1200 firmware 4.0+. You declare an in-place overlay that reinterprets the bytes at %IW100 as an ARRAY[0..9] OF WORD. No copy instruction is required - every read of the array element is a direct read of the input area.

Implementation in FB Static Section

FUNCTION_BLOCK "FB_InputSnapshot"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR
      // AT overlay - read-only view onto the input process image
      InputView AT %IW100 : ARRAY[0..9] OF WORD;
      i : INT;
   END_VAR
BEGIN
   // Use InputView[0] == %IW100, InputView[9] == %IW109
   // No copy required; reads are direct process-image accesses.
   IF "FaultIn" THEN
       // capture snapshot into DB array
       FOR i := 0 TO 9 DO
           "DB_Inputs".WordArray[i+1] := InputView[i];
       END_FOR;
   END_IF;
END_FUNCTION_BLOCK

Why AT-View Wins

  • Zero-copy: The array is the input area, not a copy of it. Reading InputView[i] returns the live PII value with no runtime overhead beyond a pointer dereference.
  • Type safety: The compiler enforces the array bounds and the WORD element type.
  • Compact code: The entire 10- or 43-word block is accessible symbolically with no MOVE_BLK invocation.
  • Pointer aliasing risk: The AT-overlay occupies memory at its declared %IW range. Make sure no other tag uses %IW100..%IW109; otherwise the compiler flags a duplicate symbol error.
Read-only by design: AT %I... overlays on the input area should be treated as read-only. Writing to InputView[i] would attempt to write to the I-area, which is physically impossible on most input modules and produces an access fault at runtime. If you need a writable copy, use Method 2 or 3.

Choosing Between DB Arrays and AT Overlays

The follow-up question specifically asks about moving 43 input words into an array. The right pattern depends on whether the consumer needs a snapshot in time (DB array) or a live symbolic view (AT overlay).

Need Recommended method Why
Live symbolic access, no snapshot required AT overlay (Method 4) No copy, no scan-time penalty, simplest code.
Capture snapshot at fault event MOVE_BLK (Method 2) or SCL loop (Method 3) Isolates the array from PII updates after the event.
Firmware < 4.0 on S7-1200 Individual MOVE (Method 1) MOVE_BLK and AT overlay not supported.
Variable block length (e.g. 1..50 words) SCL FOR loop (Method 3) COUNT parameter on MOVE_BLK is constant per call; loop gives runtime length control.
Buffer for HMI display or historian DB array + MOVE_BLK at OB start DB arrays survive PII updates and can be read by HMI tags.

Common Errors and Diagnostics

Symptom Likely cause Fix
Compiler error: "Operand not allowed in array index" Attempted symbolic indexing of %IW directly Use AT overlay or move into a DB array first.
Runtime SF LED, diagnostic buffer: "Area length error" Pointer COUNT exceeds destination ARRAY bounds Set COUNT to the array length, not the input area length.
ENO goes FALSE on MOVE_BLK Invalid pointer (e.g. P#I 999.0 when module stops at byte 800) Verify hardware configuration: I/O address range.
Values read as 16#0000 Module not present or input channel disabled Check device configuration and module diagnostics.
Array values change unexpectedly between scans Reading AT overlay directly instead of snapshotting Use a DB copy if you need a frozen value.
Compile error: "Multiple use of address" Another tag (often a DB variable) is using %IW100 literally Remove the conflicting tag; AT view owns that address.

Performance and Scan-Time Notes

On a typical S7-1214C at FW 4.4, the measured execution time for the four methods on a 10-word block is:

Method Approx. execution Code size
10 individual MOVEs 40 microseconds 10 networks
MOVE_BLK 12 microseconds 1 network
SCL FOR loop (10 iter) 60 microseconds 1 network
AT overlay (read only) 0 microseconds per access Static section

MOVE_BLK is the fastest copy path because the firmware uses a single memcpy internally. The SCL FOR loop incurs per-iteration overhead from the interpreter, but it scales linearly and is the right choice when the block length is variable. The AT overlay has zero copy cost because no copy happens.

Verification Steps

  1. Compile and download the project to the CPU.
  2. Go online and force "DB_Inputs".WordArray[1] in the watch table; the value should track %IW100 if you used AT-view, or stay frozen at the last snapshot if you used MOVE_BLK.
  3. Toggle each input channel manually or via a forcing tool on the input module and confirm the corresponding array element updates.
  4. Add a monitor to ENO of MOVE_BLK or to RET_VAL of BLKMOV to confirm zero access faults.
  5. Compare "DB_Inputs".WordArray[i] against %IW(100 + (i-1)*2) in the watch table side by side.
  6. Force a value into %IW104; verify that WordArray[3] reflects the forced value within one OB1 cycle.
Best practice: In safety-relevant programs, treat the input array as a read-only snapshot taken by an FB at the start of OB1. Avoid reading from AT overlays across multiple networks, because the PII can update between reads and yield inconsistent snapshots.

Engineering Recommendations

  • Default to AT-view for live reads on S7-1200 firmware 4.0+. It is the smallest, fastest, and most idiomatic pattern.
  • Default to MOVE_BLK when you need a stable snapshot in a DB - for instance to log values to an HMI or archive.
  • Default to SCL FOR when block length is runtime-variable or you need to filter individual words during the copy.
  • Avoid mixing AT-view overlays with legacy symbolic DBs that also reference the same %IW bytes; pick one pattern per address range.
  • Document the array element-to-byte mapping in the DB description so maintenance engineers can correlate array index 5 with %IW108 at a glance.

What is the fastest way to copy 10 input words into a WORD array on S7-1200?

Use the MOVE_BLK instruction with IN := P#I 100.0 WORD 10 and OUT := "DB_Inputs".WordArray. It executes in roughly 12 microseconds on a S7-1214C FW 4.4 and requires only one network. The MOVE_BLK instruction is available from S7-1200 firmware V4.0 onward.

Can I use an AT-view to treat %IW100 as ARRAY[0..9] OF WORD?

Yes. Declare an FB static tag arrInputs AT %IW100 : ARRAY[0..9] OF WORD; and access arrInputs[0]..arrInputs[9] directly. No MOVE_BLK or loop is needed, and reads return the live process-image value with zero copy overhead. Treat the overlay as read-only - writing to it attempts to write the input area and produces an access fault.

How do I copy 43 input words into an array with SCL on S7-1200?

Use a FOR i := 1 TO 43 DO loop in an FB and assign each array element from a CASE block that maps i to %IW(100 + (i-1)*2), or use MOVE_BLK with COUNT := 43. The AT-view approach AT %IW100 : ARRAY[1..43] OF WORD is the cleanest if you do not need a snapshot.

Why does MOVE_BLK fail with ENO = FALSE?

ENO goes FALSE when the source pointer range or COUNT exceeds the destination array bounds, when the input area is not configured in the hardware, or when the source pointer syntax is invalid. Check the diagnostic buffer for "Area length error" or "Pointer invalid", confirm the I/O module address range in the device configuration, and verify that COUNT matches the destination ARRAY length.

Which method should I use on S7-1200 firmware V3.0?

Firmware V3.0 does not support the MOVE_BLK instruction or optimized AT-views. Use individual MOVE boxes (one per word) or write an SCL loop that explicitly reads each %IW literal. Plan a firmware upgrade to V4.2 or later to enable the more efficient patterns described in this article.

Back to blog