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/GETIOcoverage 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:
- Open the device view of the PROFINET IO device (Cognex 5100, SINAMICS, ET 200, etc.).
- Select the submodule that provides the input data of interest (for the Cognex 5100 this is typically the input slot 0 / subslot 1).
- In the inspector window go to Properties > System constants. Note the name, e.g.
"Cognex5100_InputData", of typeHw_SubModule. - Either pass the symbolic constant directly to
LADDR, or read its numeric value with a cross-reference and store it in a temporaryHW_IOtag.
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
);
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:
-
GETIOreads the entire input area of the addressed submodule, regardless of length. The targetRECORDmust be sized to match the slot length exactly. -
DPRD_DATreads a defined-length range.RECORDmay 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
-
Passing W#16#… to LADDR. The CPU does not raise a compile error in every case, but the call returns
80A3at runtime. Always use the symbolic HW_IO constant. -
Passing P#… literals to RECORD. The compiler may silently convert these into an empty VARIANT, leading to
80C1at runtime. -
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. -
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
GETIOif you want to read the whole image regardless of declared length. - 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.
-
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
- Compile and download the project. TIA Portal should not report unresolved symbols for the instruction.
- Online > Devices & networks, open the Cognex 5100 device. Confirm the input submodule has status OK and that its AR (application relationship) state is Established.
- 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.
- Add a temporary
RetValin the watch table. The value should remain0for healthy reads. - For fault injection, power-cycle the camera. The next
DPRD_DATcall should return80A0or80B0depending on timing. Recover the camera and confirm the call returns to0without CPU stop. - 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 ofDPRD_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.
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.