Reading Consistent Data with DPRD_DAT on S7-1500: SCL Examples

David Krause12 min read
S7-1200SiemensTutorial / 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

Reading consistent process data from PROFINET IO devices and DP standard slaves is a recurring task in machine vision and high-speed I/O applications. On the S7-300 family this is handled by the system function SFC14 (DPRD_DAT), called from a data block with a WORD hardware address and a POINTER parameter. On the S7-1200 and S7-1500 the same functionality is exposed as the extended instruction DPRD_DAT, but the parameter interface has changed: LADDR now expects an HW_IO (hardware identifier) and RECORD expects a VARIANT rather than an ANY pointer.

This article gives an engineer-to-engineer walkthrough of how to migrate a working S7-300/SFC14 call (for example, pulling a 64-byte inspection buffer from a Cognex In-Sight 5100) to the S7-1500 in TIA Portal V20 using SCL. It covers the correct SCL syntax, how to build a VARIANT pointer, the practical alternative GETIO, RET_VAL diagnostics, and field-verified caveats when integrating third-party vision cameras.

Prerequisites

  • STEP 7 TIA Portal V17 or later (V20 documented for the URLs cited; V18/V19 are functionally equivalent for the instructions below).
  • CPU firmware: S7-1500 firmware V2.9 or higher recommended for full DPRD_DAT / GETIO coverage of PROFINET IO submodules. S7-1200 CPUs require firmware V4.2 or higher.
  • Installed instruction library: Extended Instructions > Distributed I/O > Other / I/O. The instructions are part of the global TIA Portal instruction set and do not require a separate add-on package.
  • The PROFINET IO device or DP standard slave must be configured in the device view with a known hardware identifier (HW-I / HW identifier). In TIA Portal this is visible in the device properties under System constants as tags of type Hw_IoSystem / Hw_SubModule.
  • Knowledge of the process data length and slot. For a Cognex In-Sight 5100, the PROFINET module exposes a configurable input assembly (typically 32, 64, 128, or 256 bytes) starting at slot 0 / subslot 1.

Instruction Differences: S7-300 SFC14 vs S7-1500 DPRD_DAT

Functionally both instructions guarantee consistent reading of a contiguous process image area larger than 4 bytes. The differences live at the parameter interface level, which is the typical reason legacy code does not compile on TIA Portal.

Aspect S7-300 / SFC14 S7-1200 / S7-1500 / DPRD_DAT
Location Standard library, SFC block Extended Instructions > Distributed I/O
LADDR type WORD (e.g. W#16#0101) HW_IO (hardware identifier, e.g. 268 or symbolic constant)
RECORD type ANY pointer (P#M120.0 BYTE 64) VARIANT pointing to target area
RET_VAL INT return code INT return code; same error semantics
Call form Called as a box from STL/FBD/LAD Multi-instance capable, can be called from SCL/FBD/LAD
Consistency Up to entire process image of the slave Up to entire process image of the IO submodule

See the official TIA Portal V20 description at DPRD_DAT – Read consistent data of a DP standard slave (S7-1200, S7-1500).

Locating the Hardware Identifier (HW_IO) in TIA Portal

The HW_IO is not the same as a logical or diagnostic address. In TIA Portal V17/V18/V19/V20 it is generated automatically when the IO device is added to the project. To find it:

  1. Open the device view of the PROFINET IO device (Cognex 5100, SINAMICS, ET 200, etc.).
  2. Select the submodule that provides the input data of interest (for the Cognex 5100 this is typically the input slot 0 / subslot 1).
  3. In the inspector window go to Properties > System constants. Note the name, e.g. "Cognex5100_InputData", of type Hw_SubModule.
  4. Either pass the symbolic constant directly to LADDR, or read its numeric value with a cross-reference and store it in a temporary HW_IO tag.

Passing the symbolic constant is strongly preferred — it survives renumbering after a reconfiguration. If the symbolic constant must be resolved numerically (for example, when the symbol is unavailable from an external source), the underlying value is the fully qualified hardware identifier; on S7-1500 it is a 16-bit word in the range 0..65535.

SCL Syntax for DPRD_DAT on S7-1500

The minimal SCL call from an OB/FB/FC is:

// SCL — S7-1500
#RetVal := DPRD_DAT(
    LADDR  := "Cognex5100_InputData",   // HW_IO (Hw_SubModule)
    RECORD => "dbCameraBuffer".buffer   // VARIANT pointing to DB area
);
IF #RetVal <> 0 THEN
    // handle error — see RET_VAL table below
END_IF;

The explicit form uses a temporary variable for the return value:

VAR
    RetVal_DPRD : INT;  // 0 = OK, <>0 = error (see Siemens error table)
END_VAR

RetVal_DPRD := DPRD_DAT(
    LADDR  := "Cognex5100_InputData",
    RECORD => "dbCameraBuffer".buffer  // ARRAY[0..63] OF BYTE
);

To replicate the S7-300 line:

// S7-300 SCL/STL
my_shared_var.prfin_buffer := DPRD_DAT(
    LADDR  := W#16#101,
    RECORD => P#M120.0 Byte 64
);

the S7-1500 equivalent is:

// S7-1500 SCL — equivalent to the S7-300 line above
"dbVisionIF".prfin_buffer := DPRD_DAT(
    LADDR  := "Cognex5100_InputData",     // HW_IO replaces W#16#101
    RECORD => "dbVisionIF".merkerArea     // VARIANT over P#M120.0 BYTE 64
);
Important: In SCL on S7-1500, RECORD must be passed as a VARIANT. Direct ANY-pointer literals such as P#M120.0 BYTE 64 are not accepted at this parameter — you must use a tag (DB member, M area, or local variable) whose address the compiler resolves to a VARIANT. The absolute form P#DB10.DBX10.0 INT 12 is only valid as a generic pointer literal in expressions, not as the RECORD input of DPRD_DAT.

Building a VARIANT Pointer in SCL

Two practical patterns exist for setting up the receive area:

Pattern A — Static DB member (recommended for fixed-length buffers):

DATA_BLOCK "dbVisionIF"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
NON_RETAIN
  STRUCT
      merkerArea : ARRAY[0..63] OF BYTE;   // 64-byte scratch
      prfin_buffer : ARRAY[0..63] OF BYTE; // 64-byte process data
  END_STRUCT;
END_DATA_BLOCK

The DB member is passed as a VARIANT automatically when used at the RECORD parameter of DPRD_DAT.

Pattern B — PEEK/POKE loop (legacy workaround, do not use for new code):

FOR #i := 0 TO 63 DO
    "dbVisionIF".prfin_buffer[#i] := PEEK_BOOL(area := 16#83,
                                              dbNumber := 0,
                                              byteOffset := 120 + #i);
END_FOR;

This PEEK-based fallback was used historically when engineers could not get DPRD_DAT to accept a pointer. It is byte-by-byte, not atomic, and therefore is not consistent — the data may be torn between two process image updates. Always prefer DPRD_DAT for vision applications.

Alternative: GETIO for Full Submodule Reads

If the application does not know the precise length of the input image, or if it needs to mirror the entire input of a submodule into a structured DB, use GETIO. The signature is similar:

VAR
    RetVal_GETIO : INT;
END_VAR

RetVal_GETIO := GETIO(
    LADDR  := "Cognex5100_InputData",
    RECORD => "dbVisionIF".prfin_buffer
);

Differences vs DPRD_DAT:

  • GETIO reads the entire input area of the addressed submodule, regardless of length. The target RECORD must be sized to match the slot length exactly.
  • DPRD_DAT reads a defined-length range. RECORD may be larger than the actual process image; the instruction reads up to the configured length of the addressed input area.
  • Both guarantee consistency across the read range.

Reference: GETIO – Read all inputs of a submodule (S7-1200, S7-1500).

Use DPRD_DAT when you want to pick a subset of the input image (e.g. the first 32 bytes of a 128-byte slot). Use GETIO when you want to grab the whole submodule in one consistent call and split it downstream in SCL.

Cognex In-Sight 5100 — Practical Integration

The In-Sight 5100 is a PROFINET-capable vision system that exposes a fixed input assembly to the controller. The most common patterns for 64-byte and 128-byte results buffers are:

Cognex setting PROFINET slot length PLC target type Recommended instruction
Inspection results (16 results, short) 64 bytes ARRAY[0..63] OF BYTE DPRD_DAT
Inspection results with full string results 128 bytes ARRAY[0..127] OF BYTE DPRD_DAT or GETIO
Image data (rare on 5100) > 256 bytes Split into multiple DPRD_DAT calls per slot DPRD_DAT per slot

Working SCL example with handshakes:

// FB_VisionAcquire — cyclic read of Cognex 5100 result buffer
FUNCTION_BLOCK "FB_VisionAcquire"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 1.0
VAR
    iRetVal    : INT;
    bAcqBusy   : BOOL;
    bNewData   : BOOL;
    tLastCall  : TIME;
END_VAR
VAR_TEMP
    tInfo      : TIME;
END_VAR
BEGIN
    // Trigger acquisition once per inspection cycle
    IF "iCamTrigger" AND NOT bAcqBusy THEN
        bAcqBusy := TRUE;

        iRetVal := DPRD_DAT(
            LADDR  := "Cognex5100_InputData",     // HW_IO of input submodule
            RECORD => "dbVisionIF".prfin_buffer   // ARRAY[0..63] OF BYTE
        );

        IF iRetVal = 0 THEN
            // Successful consistent read — parse results
            "FB_ResultParser"(buffer := "dbVisionIF".prfin_buffer);
            bNewData := TRUE;
        ELSE
            "FB_VisionDiag"(iErrCode := iRetVal);  // log/raise alarm
        END_IF;

        bAcqBusy := FALSE;
    END_IF;
END_FUNCTION_BLOCK

For string data, parse the byte array into STRING after the consistent read using CHAR_TO_STRG / StrgConv or a manual byte copy. Direct casting of ARRAY OF BYTE to STRING is not supported on S7-1500.

RET_VAL Error Codes and Diagnostics

Both DPRD_DAT and GETIO return the same standardized error class structure as the legacy SFC14. The most relevant values are:

RET_VAL (hex) Meaning Recommended action
0000 No error Process RECORD data
80A0 Negative acknowledgment while reading from the IO device Check PROFINET cable, device diagnostics; verify slot is configured as input
80A1 Negative acknowledgment while writing to the IO device (GETIO does not apply) n/a for read
80A2 DP/PROFINET slot fault Check submodule, station failure, ET 200 backplane
80A3 Access to a non-existent submodule Verify HW_IO; submodule removed or unconfigured
80B0 IO device not ready / not activated Check PROFINET device name assignment, AR state
80B1 Reserved Capture, escalate to Siemens support
80B2 System error (Siemens internal) CPU restart, firmware update, escalate
80C0 Data length does not match the configured length of the submodule Resize RECORD to match IO configuration; common when migrating from 64 to 128 bytes
80C1 Number of RECORD bytes is 0 RECORD is empty, check declaration
80C2 VARIANT points to a write-only or unallocated area Check RECORD points to a valid input target (DB, M area, temp)
80C3 IO area is not assigned / not present Verify the slot is present in the device configuration

Refer to the Siemens online help in TIA Portal under DPRD_DAT > Error handling for the authoritative current list, as the encoding is consistent with the S7-300 SFC14 table.

Common Pitfalls When Migrating from S7-300 to S7-1500

  1. Passing W#16#… to LADDR. The CPU does not raise a compile error in every case, but the call returns 80A3 at runtime. Always use the symbolic HW_IO constant.
  2. Passing P#… literals to RECORD. The compiler may silently convert these into an empty VARIANT, leading to 80C1 at runtime.
  3. Optimized DB access. TIA Portal V17+ defaults to optimized access. Absolute addresses inside optimized DBs are not visible to DPRD_DAT — the instruction writes by symbolic address through the VARIANT, so this is fine. However, the declared length of the target variable must be ≥ the configured slot length.
  4. Mixed array of UDT and scalar bytes. If RECORD is a structured tag whose dynamic length is shorter than the slot, the IO is truncated silently. Use GETIO if you want to read the whole image regardless of declared length.
  5. Calling DPRD_DAT from OB1 (cyclic). The function is not retentive across OB cycles; it is safe to call from OB1 but avoid double-calling in the same cycle without a state machine guard.
  6. Calling in OB82/OB83 (diagnostic OB). A PROFINET station-fault OB will pre-empt the call and may cause 80B0. Suppress DPRD_DAT in the fault OB or stage retry logic.

Verification Procedure

  1. Compile and download the project. TIA Portal should not report unresolved symbols for the instruction.
  2. Online > Devices & networks, open the Cognex 5100 device. Confirm the input submodule has status OK and that its AR (application relationship) state is Established.
  3. Place a watch table on the receive DB. Trigger a known inspection on the camera. The first four bytes of the buffer should update atomically (no mid-update tearing) when an inspection completes.
  4. Add a temporary RetVal in the watch table. The value should remain 0 for healthy reads.
  5. For fault injection, power-cycle the camera. The next DPRD_DAT call should return 80A0 or 80B0 depending on timing. Recover the camera and confirm the call returns to 0 without CPU stop.
  6. Use Online & diagnostics > PROFINET diagnostics to confirm the slot is reporting the expected process-data length.

Troubleshooting Matrix

Symptom Likely cause Fix
Compile error: type mismatch at LADDR WORD literal passed where HW_IO expected Replace with the symbolic constant from System constants
Compile error: RECORD must be VARIANT Using ANY pointer literal or POINTER type Use a tag (DB member, M area, or local); avoid ANY literals
Runtime: RET_VAL = 80A0 PROFINET link down or device failed Check cabling, PROFINET name assignment, LED status
Runtime: RET_VAL = 80A3 Submodule does not exist or HW_ID wrong Re-export system constants; verify slot index
Runtime: RET_VAL = 80C0 Declared RECORD length < configured slot length Resize the target tag or switch to GETIO
Buffer updates only partially PEEK loop used instead of DPRD_DAT Replace with DPRD_DAT for atomic read
Buffer shows old data after camera restart PROFINET AR not re-established before read Gate DPRD_DAT on a "station OK" flag from the device

Related Functions Worth Knowing

  • DPWR_DAT — the write counterpart of DPRD_DAT, used to send a consistent output image to a DP standard slave or PROFINET IO device.
  • UBLKMOV — unconditional block move; not a PROFINET/DP instruction, but a useful workaround for moving data between optimized DBs.
  • RDREC / WRREC — acyclic record-based read/write, suitable for parameter access (e.g. reading the Cognex job number, changing inspection parameters) and not a substitute for process data.
  • PNIO_RW_REC (PROFINET instruction set) — for record-based read/write on PROFINET IO submodules without going through the legacy DP interface.
Field-proven caveat: When the Cognex 5100 is set to a variable-length output (for example, "spontaneous" data publishing), the configured slot length is the maximum possible. The actual delivered length is reflected in the first two bytes (little-endian) of the buffer. In this case, size RECORD to the maximum and parse the leading length field. DPRD_DAT will still read the whole buffer consistently; the application logic is responsible for trimming to the valid range.

FAQ

Why does my S7-1500 DPRD_DAT call compile with W#16#101 at LADDR but fail at runtime?

On S7-1500, LADDR expects an HW_IO (hardware identifier), not a logical WORD address. Passing a WORD literal often compiles because the value is just a 16-bit word, but the controller cannot map it to a real submodule and returns RET_VAL 80A3. Use the symbolic HW constant from the device > System constants view.

What is the correct SCL syntax for DPRD_DAT on S7-1500?

Use #RetVal := DPRD_DAT(LADDR := "HwSymbol", RECORD => "dbTarget".buffer); where HwSymbol is an HW_IO constant and the RECORD target is a tag (DB member or local) acting as a VARIANT. ANY-pointer literals like P#M120.0 BYTE 64 are not accepted at RECORD on S7-1500.

How is GETIO different from DPRD_DAT?

DPRD_DAT reads a defined length up to the configured slot length; GETIO reads the entire input image of the addressed submodule into a target tag of matching size. Use DPRD_DAT for partial reads and GETIO for whole-slot acquisition. Both guarantee consistency.

My buffer updates byte-by-byte, not atomically. What is wrong?

You are most likely using a PEEK-based loop (PEEK_BOOL / PEEK / WORD_TO_BLOCK_DB) instead of DPRD_DAT. PEEK reads byte-by-byte from the process image and is not consistent. Replace it with a single DPRD_DAT call into an ARRAY OF BYTE to get an atomic, consistent copy.

Which TIA Portal and firmware versions are required?

Instructions are documented for TIA Portal V20 and functionally identical from V17. S7-1500 firmware V2.9 or higher is recommended for full PROFINET coverage; S7-1200 requires firmware V4.2 or higher. Check the release notes of the specific instruction version if you are on V18 or earlier.

Back to blog