S7-1500 UDT to I/O Mapping Using TIA Portal V15.1 Pointers

David Krause24 min read
SiemensTechnical ReferenceTIA Portal
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

1. Overview and Engineering Context

When commissioning a SIMATIC S7-1500 programmable logic controller in TIA Portal V15.1 or later, the engineer frequently needs to expose a structured field device as a single symbolic variable rather than a flat list of input and output bits. A SIMATIC ET 200SP digital input module, a SINAMICS drive telegram, a Festo valve manifold, or an EtherCAT terminal can each occupy a contiguous range of process I/O. Representing that range as a User-Defined Data Type (UDT) yields three engineering benefits: the HMI and SCADA layers see one meaningful tag, the program logic operates on a single symbolic instance, and the data block can be reused with type safety across multiple stations of the same machine.

The technical question is whether the UDT can be assigned to the %I or %Q area of the S7-1500 directly, and if not, what is the supported TIA Portal workflow that delivers equivalent behavior. TIA Portal does not allow a UDT to be assigned to process I/O by drag-and-drop the way a BOOL or WORD can. The UDT instance must instead be overlaid on the I/O area, copied to the I/O area with a block move, or held in a global DB whose absolute address range is reserved. Each approach has different consequences for symbolic I/O, optimized block access, and update timing.

This reference covers the recommended techniques for S7-1500 firmware V2.0 and later in TIA Portal V15.1:

  • Direct symbolic assignment of UDT members to the I/O area via the PLC tag table
  • AT overlay of a UDT on the I/O area or on a global data block mirror
  • Pointer-based indirect addressing for arrays of UDT instances
  • PEEK and POKE library operations in SCL for absolute peripheral access
  • Process image update and access mode considerations
Note: This document is written for engineers who have completed at least one S7-1500 project in TIA Portal and are familiar with the difference between symbolic and absolute addressing.

2. UDT Structure, Alignment, and Memory Layout

A UDT in TIA Portal is a template for a structured data type that follows the IEC 61131-3 specification. It can be composed of elementary types (BOOL, BYTE, WORD, DWORD, LWORD, SINT, INT, DINT, LINT, USINT, UINT, UDINT, ULINT, REAL, LREAL, CHAR, WCHAR, DATE, TIME_OF_DAY) and other PLC data types (UDT, STRUCT, ARRAY). When the UDT is instantiated, the TIA Portal compiler lays out the members in the order declared and aligns them according to the configured access mode of the destination block.

For a UDT that contains a 14-byte payload (for example, four WORD, two DWORD, and a 6-byte string), the total memory footprint is 14 bytes in a byte-aligned block or potentially 16 bytes if a 4-byte boundary is forced for performance. The S7-1500 CPU uses byte addressing internally, so a 14-byte UDT occupies exactly 14 bytes regardless of access mode; only the offset of each member is affected by alignment rules. This matters when the UDT is overlaid on the process image, because each member must start on a byte address that matches its type's natural alignment.

UDT member layout example (UDT_IO_14, 14 bytes payload)
Offset Name Type Comment
0.0 Status WORD Module status word
2.0 Value_1 INT Process value 1
4.0 Value_2 INT Process value 2
6.0 Setpoints DWORD Bit-packed setpoint image
10.0 Diagnostic BYTE Diagnostic code
11.0 SerialNumber ARRAY[0..2] OF BYTE 3-byte device ID

The UDT is created under PLC data types in the TIA Portal project tree. It is then instantiated either in a global data block (DB) or as a local static in a function block. In S7-1500 firmware V2.0 and later, the standard access mode is optimized by default. The instance becomes symbolic-only: it cannot be addressed by absolute address in a watch table or in classic pointer arithmetic.

UDT alignment rules differ between standard and optimized blocks. In a standard block, members are placed in declaration order with no padding. In an optimized block, the compiler may insert up to 3 bytes of padding between members to align DWORD members on a 4-byte boundary, which can shift the UDT footprint to a multiple of 4. If the UDT is overlaid on a fixed I/O area, the engineer must set the access mode of the AT-target block to standard to preserve byte-exact positioning, or compensate in the program.

Note: Symbolic I/O mapping in the device configuration (HSP-supported modules) requires that the I/O symbols be promoted to the PLC tag table. This is the supported route for modern S7-1500 work and is the basis of the technique covered in section 3.

3. Symbolic I/O Assignment in the PLC Tag Table

The cleanest engineering approach is to expose the UDT members as individually named tags in the PLC tag table. The device view in TIA Portal generates a default I/O tag for each channel of the configured module. The user can rename the tag and assign it a data type. The rename and the data type change are stored in the project's tag table and persist across compiles.

For a UDT containing both bit and word members, declare the individual tags first, then declare the UDT in a global DB. The UDT is populated by the program logic in OB1 using the symbolic tag names. This pattern keeps the I/O area fully symbolic, supports the standard optimized access mode, and allows the HMI to bind directly to either the UDT members in the DB or to the I/O tags themselves. The trade-off is that two copies of the same data exist: one in the process image and one in the DB. The application is responsible for keeping them in sync, which is normally done in OB1 with a single move block at the start of the cycle for inputs and at the end of the cycle for outputs.

Symbolic I/O to UDT instance mapping
I/O address PLC tag Data type UDT target
%I0.0 Module1.Status_0 BOOL MyUDT.Valve1_Open
%I0.1 Module1.Status_1 BOOL MyUDT.Valve1_Closed
%IW2 Module1.PressureRaw INT MyUDT.Pressure_kPa
%Q4.0 Module1.Coil_A BOOL MyUDT.CoilA
%QW6 Module1.SetpointRPM INT MyUDT.SetpointRPM

This layout is fully supported and is the recommended pattern for new projects. The drawback is that there is no direct bind from the UDT to the I/O area; the program must move the data explicitly. For a single UDT this is a small amount of code. For a panel of 50 similar modules, the engineer typically uses a parameterized function block with a starting input address and a starting output address, then calls the FB once per module with a different instance DB.

The PLC tag table supports the IEC 61131-3 notion of "symbolic I/O" introduced with S7-1500 firmware V1.8. The symbolic name in the tag table is used by the compiler to generate readable cross-references and to allow the HMI to browse to the tag by name. The tag table is exported to XML and can be merged with a multi-user engineering server for parallel development.

4. The 16-bit Output Word Overwrite Behavior

When the engineer assigns a single output bit from a 16-bit output word to a PLC tag, the S7-1500 CPU does not preserve the rest of the bits in the same word through a single bit-instruction write. Each bit write is compiled to a read-modify-write of the surrounding byte. Because the CPU is a little-endian byte machine, an individual bit write at %Q4.0 compiles to: read %QB4, mask in the new bit at position 0, write %QB4 back. The other 7 bits in the byte are preserved.

However, if the user writes to a WORD that overlaps the same output area, the entire word is written in one bus cycle. This can cause a transient flicker on the other bits in the word if the application is reading the process image between the two writes. The official Siemens FAQ entry 109736941, With S7-1500, why is the complete output word overwritten when you define single addresses from this word as PLC data type?, documents this exact behavior and provides a workaround using the AT view or by aligning data types to a 16-bit boundary.

Siemens FAQ 109736941: S7-1500 16-bit output word overwrite

The practical consequence for UDT work is: never mix bit-level symbolic writes and word-level symbolic writes in the same output area. Choose one of the following patterns:

  1. Use byte-granular or word-granular symbolic writes only
  2. Mirror the I/O area in a global DB and write the entire mirror word with one move at the end of the cycle
  3. Use slice access (%Q4.0:BOOL versus %QB4:BYTE) and combine bits with explicit mask logic in a single MOV instruction
  4. Use the AT overlay pattern described in section 5 so the UDT member writes are compiled to a single BLK_MOV of the surrounding area
Warning: If the application uses both single-bit outputs from a UDT member and a WORD output from the same UDT instance pointing at the same I/O word, the bit writes can be lost during the next cycle. Always review the compiled block I/O list in the project tree under PLC tags > I/O for the affected area, and use the watch table to record the value of each bit before and after the word write.

5. AT Overlay Technique for UDT on I/O

The AT overlay instruction is the standard S7-1500 mechanism for reinterpreting the same memory area as a different data type. In TIA Portal SCL, the syntax is:

AT "Operand" : "Type" := "InitialValue";

When the operand is a P# pointer into the I/O area, the AT view allows the program to treat the I/O area as if it were a UDT instance. For example, to overlay a 14-byte UDT on the input area starting at %IB0:

VAR
    InputsAT  AT P#%I0.0 BYTE 14  : UDT_IO_14;
    OutputsAT AT P#%Q0.0 BYTE 14  : UDT_IO_14;
END_VAR

The compiler treats InputsAT and OutputsAT as UDT-typed symbols that point to the input and output process image respectively. The HMI can bind to InputsAT.Pressure_kPa or to %IW2 interchangeably. The program code reads InputsAT.Status_0, modifies it, and writes OutputsAT.SetpointRPM without addressing individual absolute bits.

AT overlay against process I/O
Symbol AT operand Type Underlying address
InputsAT P#%I0.0 BYTE 14 UDT_IO_14 %IB0..%IB13
OutputsAT P#%Q0.0 BYTE 14 UDT_IO_14 %QB0..%QB13
Drv1In P#%I100.0 BYTE 14 UDT_Drive_14 %IB100..%IB113
Drv1Out P#%Q100.0 BYTE 14 UDT_Drive_14 %QB100..%QB113

The AT overlay is available in SCL only, not in LAD or FBD. In a function block, the AT view can be declared in the static area; in a function, in the temp area. The compiler requires that the AT operand point to a memory area of the same or larger size than the overlaid type, and the type's total size must equal the declared AT operand size, in bytes.

For an array of UDTs assigned to sequential I/O slots, declare an ARRAY of AT overlays. The total size of the array must match the total I/O area:

VAR
    SlotInputs : ARRAY[1..50] AT P#%I0.0 BYTE 14 : UDT_IO_14;
END_VAR

The compiler lays out 50 contiguous 14-byte blocks starting at %IB0. The index SlotInputs[3] accesses the third block. This is the cleanest pattern for a 50-channel I/O panel of identical modules. The size of the I/O area is 50 * 14 = 700 bytes, occupying %IB0..%IB699.

The AT overlay is not a copy. Reading InputsAT.Status_0 reads directly from the input process image at the time of access. If the I/O area is configured as isochronous in the device configuration, the read happens against the most recent hardware update synchronized to the PROFINET cycle. Otherwise, the read returns the process image that was last updated at the start of OB1 or the last hardware interrupt OB. For applications that need consistent I/O across the entire UDT, the engineer should configure the module as isochronous and read the UDT inside the assigned isochronous OB.

Note: AT overlays are not allowed on the peripheral I/O area (%I:P, %Q:P). The process image is the only valid target. Reading from the process image at a known scan position eliminates the read-during-write race that direct peripheral access would introduce.

6. Indirect Addressing with POINTER, ANY, and VARIANT

When the I/O slot number is computed at runtime, the engineer needs a pointer. S7-1500 supports three pointer flavors:

  • POINTER: a typed pointer with area and byte offset, declared as POINTER TO BYTE or POINTER TO UDT_IO_14
  • ANY: a 10-byte area pointer with additional repetition count, declared as ANY
  • VARIANT: a generic pointer to any data type or data block, declared as VARIANT

For a runtime-selected UDT instance, the VARIANT type is the modern choice. It can hold a reference to a UDT instance, to a slice of an array, or to a memory area. The IS_VALID and IS_NULL operators check the reference, and the EQUAL operator compares two VARIANTs for pointing to the same instance.

The PEEK and POKE SCL functions read and write absolute I/O without needing a typed pointer. PEEK reads from any memory area, including the peripheral I/O area. POKE writes to any memory area except the read-only inputs. The functions are:

PEEK/POKE function library in SCL
Function Returns Description
PEEK_BOOL(area, byteOffset, bitOffset) BOOL Reads a single bit from an absolute address
PEEK(area, byteOffset) BYTE Reads one byte from an absolute address
PEEK_WORD(area, byteOffset) WORD Reads one word
PEEK_DWORD(area, byteOffset) DWORD Reads one double word
PEEK_INT, PEEK_REAL, PEEK_DINT, PEEK_LREAL numeric Typed reads
POKE_BOOL, POKE, POKE_WORD, POKE_DWORD VOID Writes to an absolute address
PEEK_BLK(area, byteOffset, dest) VOID Block read into dest VARIANT
POKE_BLK(area, byteOffset, src) VOID Block write from src VARIANT

For input-area UDT reads, the typical call is:

udtInstance := PEEK_BLK(area := 16#81, byteOffset := SlotIndex * 14, dest := udtInstance);

where area 16#81 is the input process image and 16#82 is the output process image, per the IEC 61131-3 area code map. The 14-byte UDT is read in one block operation. The dest parameter can be a VARIANT or a typed variable. This approach works in optimized blocks as long as the destination is a UDT instance in a standard or optimized DB.

The IEC area codes used in PEEK and POKE are:

IEC 61131-3 area codes for PEEK/POKE
Area code Memory area Read Write
16#81 Input process image (PII) Yes No
16#82 Output process image (PIQ) No Yes
16#83 Bit memory (M) Yes Yes
16#84 Data block (DB) Yes Yes
16#85 Instance data block (DI) Yes Yes
16#86 Peripheral inputs (direct) Yes No
16#87 Peripheral outputs (direct) No Yes

Direct peripheral access (areas 16#86 and 16#87) bypasses the process image and reads or writes the physical terminals directly. This is useful for time-critical signals but cannot be used with AT overlays, which require the process image target. The PEEK/POKE block operations (PEEK_BLK, POKE_BLK) emit a single BLKMOV or BLKMOVP instruction in the compiled code; the runtime cost is one bus cycle for the entire UDT.

Note: PEEK and POKE in S7-1500 are intrinsic instructions, not library functions. The destination VARIANT for PEEK_BLK must be of the same size and similar structure to the source area, or the runtime will raise a temporary error. The IEC area codes are documented in the S7-1500 system manual. The constant area values must be written as 16#81 rather than 129 for clarity.

7. Array of UDTs with Indexed Access

For applications with 50 or more identical I/O slots, the array of AT overlays is the most readable. The declaration:

VAR
    Module_Inputs  : ARRAY[0..49] AT P#%I0.0 BYTE 14 : UDT_IO_14;
    Module_Outputs : ARRAY[0..49] AT P#%Q0.0 BYTE 14 : UDT_IO_14;
END_VAR

creates 50 UDT overlays on the input image and 50 on the output image. The program iterates with a FOR loop:

FOR i := 0 TO 49 DO
    IF Module_Inputs[i].Healthy THEN
        Module_Outputs[i].Enable   := TRUE;
        Module_Outputs[i].Setpoint := Module_Inputs[i].Demand;
    ELSE
        Module_Outputs[i].Enable   := FALSE;
        Module_Outputs[i].Setpoint := 0;
    END_IF;
END_FOR;

The index variable i is of type INT or DINT. The compiler resolves Module_Inputs[i] to the address %I(i*14) at compile time if i is constant; if i is variable, the compiler inserts a multiplication and an indexed access. The resulting code is identical in execution time to a hand-written block of 50 individual bit operations, but the source is a single UDT-typed statement.

For dynamic slot indexing, the engineer can combine the array of AT overlays with a pointer-based access. Declare a temporary pointer to the array element:

VAR
    pSlot : POINTER TO UDT_IO_14;
END_VAR

pSlot := REF(Module_Inputs[i]);
pSlot^.Override := pSlot^.Override OR 16#0001;

The REF() operator in S7-1500 returns a pointer to an array element. The dereferenced structure field can be written through the pointer. This is the pattern for runtime selection of a slot based on a recipe or production order.

Indexed access patterns for array of UDTs
Pattern Index type Use case
Array[const] direct INT constant Compile-time slot access
Array[i] with loop variable INT variable FOR loop iteration
REF(Array[i]) POINTER TO UDT Pointer-based field writes
PEEK_BLK with offset UDT instance One-shot copy from a known offset
VARIANT to Array[i] VARIANT Generic function dispatch

For multi-dimensional arrays of UDTs, the same pattern applies. The array dimensions are multiplied in the index calculation. For an ARRAY[0..9, 0..4] OF UDT_IO_14 with each UDT 14 bytes, the address of element [r, c] is %I((r * 5 + c) * 14). The compiler inserts the multiplication automatically when the AT overlay syntax is used.

8. SCL Code Library for UDT-to-I/O Operations

Below is a working SCL code library for an S7-1500 project using TIA Portal V15.1. It demonstrates input-to-UDT, UDT-to-output, and array iteration patterns.

// UDT declaration in the PLC data types
TYPE UDT_IO_14
    STRUCT
        Status    : WORD;                     // Byte 0..1
        Pressure  : INT;                      // Byte 2..3
        Flow      : INT;                      // Byte 4..5
        Setpoints : DWORD;                    // Byte 6..9
        Diag      : BYTE;                     // Byte 10
        SerNo     : ARRAY[0..2] OF BYTE;      // Byte 11..13
    END_STRUCT;
END_TYPE

// FB with AT overlays
FUNCTION_BLOCK "FB_50_Modules"
VAR
    InputsAT   : ARRAY[0..49] AT P#%I0.0 BYTE 14 : UDT_IO_14;
    OutputsAT  : ARRAY[0..49] AT P#%Q0.0 BYTE 14 : UDT_IO_14;
    MirrorIn   : ARRAY[0..49] OF "UDT_IO_14";
    MirrorOut  : ARRAY[0..49] OF "UDT_IO_14";
    i : INT;
END_VAR

BEGIN
    // 1) Refresh input mirror at start of cycle
    FOR i := 0 TO 49 DO
        MirrorIn[i] := InputsAT[i];
    END_FOR;

    // 2) Application logic on the mirror (safe to read multiple times)
    FOR i := 0 TO 49 DO
        IF MirrorIn[i].Status = 16#0001 THEN
            MirrorOut[i].Setpoints := 16#0000_0001;
        ELSE
            MirrorOut[i].Setpoints := 16#0000_0000;
        END_IF;
    END_FOR;

    // 3) Write outputs at end of cycle
    FOR i := 0 TO 49 DO
        OutputsAT[i] := MirrorOut[i];
    END_FOR;
END_FUNCTION_BLOCK

For a UDT that must be moved in one operation without an AT overlay, use a single BLKMOV or the SCL direct assignment:

// One-shot copy of an entire UDT to the output process image
OutputsAT[3] := MirrorOut[3];

// Same operation with absolute address via AT
OutputsAT[5].Setpoints := 16#0000_0000;

// Block move with explicit instruction
BLKMOV(SRC := MirrorOut[7], DST := OutputsAT[7]);

The direct UDT-to-UDT assignment compiles to a single block move of 14 bytes. There is no per-field overhead. The compiler preserves the byte order of the source UDT, including any padding introduced by alignment settings.

For pointer-based dispatch into an array of UDTs, the REF() operator returns a typed pointer that can be passed to a function block expecting a POINTER TO UDT_IO_14 parameter. The function can then modify the underlying instance through the pointer without copying the entire 14-byte UDT across the call boundary.

Note: The assignment MirrorIn[i] := InputsAT[i] copies from the AT overlay into a global data block instance. The compiler recognizes the size match and inserts a single block move. There is no need for a separate BLKMOV instruction unless the destination is in a different optimization class, in which case an explicit BLKMOV or UMOVE_BLK may be required to avoid the access to optimized block from standard context compiler warning.

9. Optimized Block Access Considerations

S7-1500 firmware V2.0 and later, with the default TIA Portal project settings, creates data blocks with optimized block access enabled. In optimized blocks:

  • Members are addressed symbolically only; the absolute address is hidden from the program
  • Members are not necessarily stored in declaration order; the compiler may reorder for cache efficiency
  • Pointer arithmetic with POINTER or ANY requires special care because the absolute offset is not visible to the user
  • Download without reinitialize is supported for individual changed tags

The AT overlay of a UDT on the I/O area works in optimized blocks because the AT operand is itself an absolute address. The compiler knows the size of the AT operand and validates the overlaid UDT type at compile time. There is no ambiguity.

The PEEK and POKE functions in SCL also work in optimized blocks, because they are intrinsic operations that address the I/O directly. The VARIANT-based block read (PEEK_BLK) and block write (POKE_BLK) require that the source or destination VARIANT be valid, and the variant must be of a type compatible with the target area. The compiler does not check the variant's underlying type compatibility at compile time; it inserts a runtime check that raises a temporary error in the event of a mismatch.

Optimized vs. standard access mode behavior
Feature Optimized block Standard block
Symbolic addressing Required Symbolic or absolute
AT overlay on I/O Supported Supported
PEEK/POKE in SCL Supported Supported
POINTER to DB member Not directly supported; use REF() Supported
Download without reinitialize Yes, single tags only Yes, full block
Retention Configurable per tag Configurable per area
Memory layout Compiler-managed Declaration order

For projects that need to mix pointer-based access with UDT-typed access, the recommended pattern is to keep the I/O mirror in a global DB with standard access mode. The DB then acts as a typed interface to the I/O area. Pointer-based legacy code can still address the DB by absolute byte offset, while new code can use the UDT-typed view. The DB must be configured with non-optimized in the block properties.

When the I/O mirror DB is configured as optimized, the address of a member is not stable across compilation. The REF() operator must be used in place of any direct pointer arithmetic. The pointer returned by REF() is a symbolic pointer and is resolved at compile time against the current memory layout; if a new member is added above the referenced member, the pointer automatically tracks the new offset.

Note: If the project must support downloading individual changed tags without reinitializing the entire block, the block must be configured with optimized access. The download to a standard block in RUN mode requires a full reinitialization, which would lose the I/O mirror contents. For runtime-stable UDT-to-I/O mapping, optimized is the correct choice for new projects; for legacy migration, standard is the path of least disruption.

10. Verification, Commissioning, and Diagnostics

After the UDT is overlaid or copied to the I/O area, the engineer must verify the mapping in the commissioning phase. The recommended sequence is:

  1. Build and download the project to the S7-1500 CPU. The TIA Portal compiler emits an I/O list under the device configuration. Open the list and confirm that each module address is in the expected byte range. Cross-check the I/O list against the UDT overlay declaration.
  2. Open a watch table and add the UDT-typed symbols (e.g., InputsAT[0].Status). Force a single input bit at the module terminals and observe the corresponding UDT member change in the watch table. Toggle each bit and confirm the matching member updates within one OB1 cycle.
  3. Use the trace function in TIA Portal to record one full cycle of the OB1 execution. The trace shows the input process image at the start of OB1 and the output process image at the end of OB1. The UDT members should match the trace samples within one scan.
  4. PLCSIM simulation: TIA Portal V15.1 PLCSIM supports the full S7-1500 instruction set. Run the project in PLCSIM, drive the simulated inputs, and verify the UDT-typed view. The PLCSIM Force panel can manipulate individual bits of the simulated input area, which is useful for unit testing the UDT-to-I/O logic without hardware.
  5. HMI verification: bind an HMI tag to a UDT member and to the corresponding process I/O tag. Both should display the same value. If they diverge, the AT overlay or the BLKMOV is not synchronized correctly. Verify the I/O list again and check the OB priority.
  6. Test the 16-bit output word: deliberately exercise the output word with a UDT member write and a separate bit write, and observe whether the other bits in the word are affected. If they are, the application has hit the FAQ 109736941 scenario; switch to a mirror-based write pattern.

For runtime diagnostics, the S7-1500 CPU maintains diagnostic information for each configured module. The diagnostic buffer entry includes the slot number, the channel that failed, and the type of fault. The application can read the diagnostic record with the RDREC or GETIO system function block. The diagnostic data is mapped to a UDT-typed input record that the application can route to the HMI alarm log.

Common commissioning failures and remedies
Symptom Likely cause Remedy
UDT member reads always 0 I/O not in process image Enable process image in device config
UDT member reads garbage Address offset misaligned Check AT operand byte count
Other bits flicker on word write FAQ 109736941 scenario Mirror in DB and write whole word
PEEK returns temporary error VARIANT type mismatch Match UDT size to PEEK_BLK length
Pointer arithmetic fails in optimized DB Address not stable Use REF() instead of POINTER arithmetic
OB1 does not see new I/O Update not configured Set module update to OB1 in device config

The I/O list also reports the assigned process image partition (PIP). S7-1500 supports up to 32 PIPs, each with its own update OB. For a UDT that must be read in a time-critical OB (for example, OB40 hardware interrupt), assign the corresponding module to a PIP that is updated by that OB, and declare the AT overlay in the OB itself rather than in OB1.

Note: When forcing I/O via the TIA Portal watch table in RUN mode, the CPU does not write the forced value to the physical output terminals. The forced value is applied to the output process image only. The physical terminal is de-energized. This is the expected safety behavior and is the reason for the force semantics in S7-1500. For productive testing without force, drive the actual field signal and observe the UDT member.

11. Frequently Asked Questions

Can I assign a UDT directly to %I or %Q in the device configuration?

No. TIA Portal allows individual BOOL, BYTE, WORD, and DWORD tags to be assigned to I/O addresses in the device configuration, but UDT-typed tags cannot be assigned directly. The UDT must be overlaid on the I/O area with an AT view, or copied to or from the I/O area in the program logic. The recommended pattern for 50 identical modules is an array of AT overlays on a contiguous I/O block: VAR Inputs : ARRAY[0..49] AT P#%I0.0 BYTE 14 : UDT_IO_14; END_VAR.

Why does writing one output bit clear the other bits in the same word?

This is the 16-bit output word overwrite behavior documented in Siemens FAQ 109736941. A word write replaces the entire word in one bus cycle, while a bit write is a read-modify-write of the surrounding byte. If the application mixes bit-level and word-level writes to the same I/O area, a transient flicker can occur on the other bits. Use byte- or word-aligned writes only, or use a global DB mirror that is written in one move at the end of the cycle, as described in Siemens FAQ 109736941.

How do I address a UDT instance in a 50-slot panel by a runtime index?

Declare an ARRAY of AT overlays: VAR Inputs : ARRAY[0..49] AT P#%I0.0 BYTE 14 : UDT_IO_14; END_VAR. The index variable i can be a DINT. Inside the program, Inputs[i].Status addresses the byte at %I(i*14) and %I(i*14+1). For pointer-based access, use REF(Inputs[i]) in SCL, or PEEK_BLK(area := 16#81, byteOffset := i * 14, dest := udtInstance) for a one-shot block copy.

Does PEEK work in optimized blocks on S7-1500?

Yes. The PEEK and POKE functions in SCL are intrinsic operations that address the I/O area directly. They are available in optimized blocks and they work against the IEC area codes: 16#81 for inputs, 16#82 for outputs, 16#83 for bit memory, 16#84 for DB, 16#86 for direct peripheral inputs, 16#87 for direct peripheral outputs. The destination of PEEK_BLK and the source of POKE_BLK must be a VARIANT of a compatible type; the compatibility is checked at runtime and a temporary error is raised on mismatch.

What is the difference between process I/O and direct peripheral I/O?

Process I/O (%I, %Q) is the image of the physical input and output terminals maintained by the CPU. It is refreshed automatically at the start of OB1 for inputs and at the end of OB1 for outputs. Direct peripheral I/O (%I:P, %Q:P) reads and writes the physical terminals directly, bypassing the process image. Direct access is used for time-critical or single-scan operations but is slower per access than process I/O and cannot be used with AT overlays of a typed UDT. The peripheral areas are reachable through PEEK and POKE with area codes 16#86 and 16#87.

Can I keep the UDT-typed I/O mirror in a downloaded-without-reinitialize block?

Yes. Configure the mirror DB as optimized in the block properties and set the UDT member values to Setpoint rather than Actual for non-retentive tags. In RUN mode, individual changed tags can be downloaded without reinitializing the DB. The pointer returned by REF() automatically tracks the new member offset, so existing pointer-based code continues to work after a re-download that reorders members.

Back to blog