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:
- Individual
MOVEcalls (works on every CPU firmware). -
MOVE_BLK(formerlyBLKMOV) - one-call bulk copy from a pointer to an ARRAY. - SCL
FORloop using PE/WP-style indexed input access. - 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.
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 WORDtarget, where n matches the number of input words (10 in the question, 43 in the follow-up). - Input modules wired to
IW100throughIW(99+n)in the device configuration. Unwired addresses return16#0000, not an error. - Knowledge of how TIA Portal converts classic
IWaddresses to the new fully-qualified form:%IW100. The compiler always interprets bareIW100as 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.
- Open the OB1 or FC/FB that owns the snapshot.
- Insert an empty network for each input word.
- Drop a MOVE box; wire
%IW100toINand"MyDB".WordArray[1]toOUT1. - Repeat for
%IW102through%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
- Insert Instructions > Move operations > MOVE_BLK.
- At
IN, type the absolute pointerP#I 100.0 WORD 10. The pointer form is:P#<area> <byte.bit> <data type> <count>. AreaI= inputs,Q= outputs,M= bit memory. - At
OUT, drag the array tag"DB_Inputs".WordArray. - At
COUNT, enter the literal10or a tagiCountof type UINT.
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
%IWrange. Make sure no other tag uses%IW100..%IW109; otherwise the compiler flags a duplicate symbol error.
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
- Compile and download the project to the CPU.
- Go online and force
"DB_Inputs".WordArray[1]in the watch table; the value should track%IW100if you used AT-view, or stay frozen at the last snapshot if you used MOVE_BLK. - Toggle each input channel manually or via a forcing tool on the input module and confirm the corresponding array element updates.
- Add a monitor to
ENOof MOVE_BLK or toRET_VALof BLKMOV to confirm zero access faults. - Compare
"DB_Inputs".WordArray[i]against%IW(100 + (i-1)*2)in the watch table side by side. - Force a value into
%IW104; verify thatWordArray[3]reflects the forced value within one OB1 cycle.
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
%IWbytes; 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
%IW108at 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.