S7-1200 TIA Portal Preventing DBD Implicit DINT_TO_REAL

David Krause14 min read
S7-1200SiemensTroubleshooting
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

S7-1200 TIA Portal: Preventing DBD Implicit DINT_TO_REAL Conversion

Engineers working with the SIMATIC S7-1200 CPU family in TIA Portal V13 SP1 (and later) frequently encounter an unexpected result when copying data between DBD (double-word absolute) addresses that are declared as REAL. The instruction %DB1.DBD4 := %DB1.DBD6 silently reinterprets the source bit pattern as an integer and converts that integer to a floating-point value before writing it back. The destination no longer contains the raw 32 bits the user moved; it contains the IEEE 754 representation of an integer that just happened to share those bits. This article explains exactly why the conversion happens, walks through the bit-level mechanics, compares all known workarounds, and documents the compiler diagnostic differences between TIA Portal V13 SP1, V13 SP2, V14, V15, V16, V17, V18, V19, and V20.

Scope. The behavior is specific to the S7-1200 firmware family (CPU 1211C through CPU 1217C/DCK/DC/DC/DC, FW 4.2 through FW 4.7) and to TIA Portal projects that use absolute DBD/DBW addressing in SCL or STL. Symbolic addressing in SCL (e.g. "HMI_DB".var2) does not exhibit the same issue. CPU 1500 firmware (FW 2.x) raises an explicit compile error in V13 SP2 and later for the equivalent pattern.

Problem Description

The symptom is straightforward: a block of memory that should contain the IEEE 754 bit pattern of a known REAL value (for example, 24.7 = 0x41C5999A) instead contains a completely different pattern (for example, 0x4E838B33 = 1.103469×109) after a DBD-to-DBD move.

Item Value
Source REAL (24.7) bit pattern 0x41C5999A
Source REAL reinterpreted as unsigned DINT 1,103,468,954
Result REAL (1,103,468,954.0) bit pattern 0x4E838B33
Result REAL decimal value 1.103469e+009
Net effect on user data All 32 bits scrambled

The transfer appears to succeed: no error is raised, no warning is shown in the inspection window, and the online monitor updates. The corruption is only visible when the engineer cross-checks the destination against the source at the bit level. This is one of the most common S7-1200 data-type pitfalls documented on the Siemens Industry Online Support portal.

Minimal Reproduction Test Case

The following data block declaration in TIA Portal reproduces the behavior in the S7-1200 PLC simulator and on real hardware.

DB1 — "HMI_DB" (declaration table):

Name Data type Address Comment
var1 REAL DB1.DBD0 Source value
var2 REAL DB1.DBD4 Destination value (expected copy of var1)
var3 WORD DB1.DBW8 Buffer low word
var4 WORD DB1.DBW10 Buffer high word

SCL code (FC1, OB1, or FB body):

// Step 1 - Write 24.7 to var1
"HMI_DB".var1 := 24.7;          // expected hex: 0x41C5999A

// Step 2 - Split var1 into the two buffer words
"HMI_DB".var3 := "HMI_DB".var1.%W0;   // 0x99A? no - read low word directly
"HMI_DB".var4 := "HMI_DB".var1.%W2;   // high word

// Better, with absolute addressing in SCL:
%DB1.DBW8  := %DB1.DBW0;   // 0x99A? read low word of var1
%DB1.DBW10 := %DB1.DBW2;   // read high word of var1

// Step 3 - Reassemble - the user expects a bit-perfect copy
%DB1.DBD4 := %DB1.DBD8;    // BUG: implicit DINT_TO_REAL fires here

Monitoring on the S7-1200 shows the following online values after a single scan cycle:

Tag Expected hex Actual hex Actual decimal
var1 0x41C5999A 0x41C5999A 24.7
var2 0x41C5999A 0x4E838B33 1.103469e+009
var3 (DBW8) 0x999A 0x999A 39322
var4 (DBW10) 0x41C5 0x41C5 16837

The intermediate word-copy step (DBW8 := DBW0, DBW10 := DBW2) is bit-exact. The corruption is introduced exclusively by the DBD4 := DBD8 line.

Root Cause: Symbol-Aware Type Inference

The SCL compiler in TIA Portal V13 SP1 performs a two-step type resolution for absolute addresses:

  1. Symbol lookup. For every %DBx.DBBy reference, the compiler queries the data block declaration table. If a tag overlaps the address, the compiler retrieves the tag name and the declared data type.
  2. Type assignment. The expression is then type-checked as if the symbol were used. When the destination overlaps with a tag of type REAL, the right-hand side is forced through the standard REAL conversion ladder.

In the reproduction above, the source operand %DB1.DBD8 does not correspond to a declared tag (the user has only DBW8 and DBW10, not DBD8), so the compiler infers a raw DWORD. The destination operand %DB1.DBD4 is fully covered by the tag var2 of type REAL. The compile pipeline therefore executes an implicit DINT_TO_REAL conversion on the right-hand side before generating the STL move.

The TIA Portal online help documents the rule: "A DWord value is implicitly converted to Real, i.e. 1 becomes 1.0." This is a deliberate design choice for the SCL high-level language. The catch is that an absolute DBD address carries no symbol information, so the rule fires even when the engineer intends a pure bit-level move. The compiler does not issue a warning because, in its model, the operation is type-correct.

Why the Implicit Conversion Activates — A Closer Look

The S7-1200 SCL compiler executes the following logical sequence for %DB1.DBD4 := %DB1.DBD8:

  1. Resolve source: %DB1.DBD8 → no tag overlap → type is DWORD (signed interpretation: DINT).
  2. Resolve destination: %DB1.DBD4 → tag var2 : REAL.
  3. Type-check: REAL := DWORD → implicit DINT_TO_REAL insertion (per IEC 61131-3 table 12.6 for SCL).
  4. Generate STL: the compiler emits an ITD (Integer to Double Integer) followed by a DTR (Double Integer to Real) block before the actual MOVE (or it uses a ROUND/CONV combination depending on optimization level).

The conversion pipeline is invisible in the editor. Cross-compiling the same block in STL or LAD/STL/FBD with explicit MOVE_BLK behaves as expected because the MOVE instruction is type-agnostic and copies the 32 raw bits.

The LREAL Literal Trigger

An additional wrinkle is that floating-point literals in SCL default to LREAL (64-bit double), not REAL (32-bit single). The line:

"HMI_DB".var1 := 24.7;   // 24.7 is LREAL by default in SCL

requires an implicit LREAL_TO_REAL conversion to fit the destination. In TIA Portal V13 SP1 this conversion is silently allowed; in V13 SP2 and later it raises the error:

Datatype "LReal" cannot be converted implicitly to datatype "Real".

The fix is to type the literal explicitly:

"HMI_DB".var1 := REAL#24.7;     // explicit 32-bit REAL literal

Similarly, when assigning a literal to a DBD:

%DB1.DBD0 := REAL#24.7;   // works - no implicit LREAL conversion
%DB1.DBD0 := 24.7;         // V13 SP1: silently allowed; V13 SP2+: error

This explains why the original poster saw the LReal error only on certain code paths: the destination of 24.7 was a raw DBD with no symbolic overlap, so the compiler treated it as DWORD and rejected the LREAL → DWORD cast.

Bit-Level Walkthrough

The 32-bit IEEE 754 single-precision encoding of 24.7 is built up as follows:

Field Bits Value (24.7)
Sign (bit 31) 0 Positive
Exponent (bits 30-23) 10000011 131 - 127 = 4
Mantissa (bits 22-0) 10001011001100110011010 0.54375
Full pattern 0x41C5999A 1.54375 × 24 = 24.7

Reinterpreting the same bit pattern as an unsigned integer yields 1,103,468,954. The compiler's implicit DINT_TO_REAL then computes the IEEE 754 encoding of 1,103,468,954:

Field Bits Value (1,103,468,954)
Sign (bit 31) 0 Positive
Exponent (bits 30-23) 10011101 157 - 127 = 30
Mantissa (bits 22-0) 00000111000110001011011 ~0.0554
Full pattern 0x4E838B33 1.0554 × 230 ≈ 1.103469×109

This is the value the engineer observes in var2. The 32 bits are not corrupted by a hardware fault; they are correctly generated by the conversion pipeline, just not the pipeline the engineer intended.

Workarounds

Five production-ready workarounds are documented. Each has a different impact on readability, runtime, memory footprint, and portability to other Siemens platforms.

Workaround 1 — Word-by-Word Transfer

The most direct fix. Replace the DBD move with two DBW moves that do not collide with any symbolic REAL declaration.

%DB1.DBW4 := %DB1.DBW6;   // low word  - 0x999A
%DB1.DBW6 := %DB1.DBW8;   // high word - 0x41C5

Pros: No additional code, works on every TIA Portal version, zero scan-time overhead. Cons: The intermediate "swap" pattern (low to high destination, high to low source) is easy to misread.

Workaround 2 — AT Overlay View

Use the SCL AT feature to declare a DWORD view over the same memory as the REAL tag. The compiler treats the two names as type-distinct but memory-identical, and the DWORD view disables the implicit conversion.

DATA_BLOCK "HMI_DB"
  VAR
    var1 : REAL;           // DBD0 - 4 bytes
    var2 : REAL;           // DBD4 - 4 bytes
    var3 : WORD;           // DBW8 - 2 bytes
    var4 : WORD;           // DBW10 - 2 bytes
  END_VAR
  VAR
    var1_dw AT var1 : DWORD;
    var2_dw AT var2 : DWORD;
  END_VAR
END_DATA_BLOCK

// In the program section
"HMI_DB".var2_dw := "HMI_DB".var1_dw;   // pure 32-bit copy, no conversion

The AT overlay pattern is the recommended approach for buffer-style bit operations and is supported on S7-1200 from FW 4.0 onward and on every S7-1500 firmware version. See the Siemens SIMATIC S7-1200 Programmable Controller System Manual for the exact declaration syntax and stack impact. S7-1200 Programmable Controller System Manual, section on AT view.

Workaround 3 — Dedicated DWord Function Block

Create a small FB with a single DWORD → DWORD transfer. The FB signature forces the compiler to keep the type as DWORD end-to-end, breaking the symbol chain that triggers the REAL conversion.

FUNCTION_BLOCK "FB_DWordCopy"
  VAR_INPUT
    IN1 : DWORD;   // raw 32 bits
  END_VAR
  VAR_OUTPUT
    OUT1 : DWORD;  // raw 32 bits
  END_VAR
  VAR
    // no internal state
  END_VAR
BEGIN
    OUT1 := IN1;   // single MOVE in compiled STL
END_FUNCTION_BLOCK

// Call site
"FB_DWordCopy"(IN1 := %DB1.DBD8, OUT1 => %DB1.DBD4);

The SCL MOVE instruction compiles to a single STL UD (Unconditional Double-word move) when both operands are DWORD. The block is reusable across the project and provides one central place to add diagnostics (signalling, heartbeat) if required.

Workaround 4 — Symbolic Addressing with Explicit Cast

When both the source and the destination are exposed as symbols of the same REAL type, the implicit conversion is harmless because the value survives the round-trip. Use a tag-to-tag assignment and the REAL_TO_DWORD cast to make the conversion intent explicit at the call site.

// Reading the raw bits of var1 into a DWORD variable
"HMI_DB".var2_dw := DWORD#16#41C5999A;            // constant path
"HMI_DB".var2_dw := REAL_TO_DWORD("HMI_DB".var1); // explicit
// var2 now contains the same 32 bits as var1, because both are
// operated on as DWORD by the compiler

For documentation, the explicit REAL_TO_DWORD cast (or its IEC alias CONV_REAL_TO_DWORD) makes the conversion auditable in the code review. The TIA Portal V20 data-type conversion reference for S7-1500/S7-1500 lists the full matrix of supported explicit conversions; the same operators are available on S7-1200 with the SCL instruction set documented in the S7-1200 System Manual.

Workaround 5 — STL Direct Move (LAD/FBD/STL Editor)

Program the same logic in a LAD/FBD/STL block using the box-style MOVE instruction. The MOVE box is type-agnostic at the bit level and will copy 32 raw bits regardless of any underlying symbolic declaration.

// LAD/FBD network
// --[ MOVE ]--
//   IN  : %DB1.DBD8   (treated as 32 bits)
//   OUT : %DB1.DBD4   (treated as 32 bits)

This is the most portable fix across the S7-1200/S7-1500/S7-300/S7-400 families and is the only pattern that works on every legacy and current CPU. The trade-off is loss of SCL readability.

Workaround Comparison Matrix

Approach Lines of code Scan-time cost S7-1200 support S7-1500 support Readability Reusability
Word-by-word 2 ~ 2 µs All FW All FW Medium Low
AT overlay +2 declaration 0 (same MOVE) FW 4.0+ All FW High Medium
DWord FB +15 (FB def) 1 FB call All FW All FW High High
Explicit cast 1 1 CONV call All FW All FW High Medium
STL MOVE box 1 1 MOVE All FW All FW Medium Low

The AT overlay (Workaround 2) and the DWord FB (Workaround 3) are the two patterns that scale best on large projects. For one-off code, the word-by-word fix (Workaround 1) and the STL MOVE box (Workaround 5) are the smallest patches to existing code.

Compiler Diagnostic Differences Across TIA Portal Versions

Siemens quietly tightened the SCL type-checker between V13 SP1 and V13 SP2. The same code compiles differently depending on the portal version in use:

TIA Portal version S7-1200 behavior on %DB1.DBD4 := %DB1.DBD8 (var2 : REAL) S7-1500 behavior on the same line
V13 SP1 Compiles, implicit DINT_TO_REAL fires at runtime Compiles with warning
V13 SP2 Compiles, implicit DINT_TO_REAL fires at runtime Hard error: "LReal cannot be converted implicitly to DWord"
V14 / V14 SP1 Compiles, warning added ("Implicit conversion REAL ← DINT") Hard error
V15 / V15.1 Compiles with warning Hard error
V16 / V17 Compiles with warning, online test reveals conversion Hard error
V18 / V19 / V20 Compiles with warning Hard error

The behavior is not yet unified across the two CPU families as of TIA Portal V20. Engineers who maintain a single SCL source base for both S7-1200 and S7-1500 should adopt Workaround 2 (AT overlay) to be portable.

Disabling IEC Checks — Why It Is Not Recommended

The SCL property "IEC checks" in the block properties can be turned off. The common belief is that disabling IEC checks suppresses the implicit conversion. This is incorrect. Disabling IEC checks only suppresses the compile-time error/warning messages for non-IEC-conforming constructs (such as direct access to DBD); the implicit DINT_TO_REAL conversion is part of the IEC 61131-3 type system itself and is not affected by the toggle. The actual STL code generated is identical with the flag on or off.

Safety impact. Some PLC code-validation tools and Siemens Safety Integrated acceptance tests require IEC checks to remain enabled. Disabling the flag to silence this particular warning is likely to fail a Functional Safety (SIL 2/3) audit and should not be used as a fix.

Best Practices for S7-1200 Bit-Level Buffer Operations

  1. Prefer symbolic addressing. Use the tag name ("HMI_DB".var2_dw) instead of the absolute address (%DB1.DBD4) whenever the source/destination is exposed as a tag. The compiler cannot infer a REAL cast from a DWORD-typed tag.
  2. Use AT overlays for buffers. When a tag of type REAL, DINT, or INT must be addressed as raw bits, declare a sibling AT view of type DWORD, WORD, or BYTE. This is the official Siemens-recommended pattern for the S7-1200 family.
  3. Type all floating-point literals explicitly. Always write REAL#24.7 or LREAL#24.7. The default LREAL behavior will break in V13 SP2+ for S7-1500 and is a latent bug on S7-1200.
  4. Cross-check online values against offline declarations. The pattern described here produces plausible-looking online values that are very different from the offline declaration. Add a watch table that reads the destination with the "HEX" display format during commissioning.
  5. Prefer a single MOVE_BLK / MOVE for bulk operations. The SCL MOVE keyword compiles to a single UD (or UN) and is type-agnostic. It is the only high-level construct that produces bit-exact copies across the entire address space.
  6. Document any non-symbolic absolute DBD access. Add a comment with the reason for the absolute access and a link to the relevant Siemens Online Support FAQ so that future maintainers understand the intent.
  7. Add an "Implicit conversion" filter to the compile log. In TIA Portal V16+, the message class for implicit conversions can be filtered and exported to a CSV. Use this during code reviews to catch the pattern across the project.

Related Siemens Resources

Frequently Asked Questions

Why does the S7-1200 silently convert 0x41C5999A to 0x4E838B33 on a DBD-to-DBD copy?

Because the destination %DB1.DBD4 overlaps a tag of type REAL (var2), the SCL compiler inserts an implicit DINT_TO_REAL conversion before the move. The source bits (1,103,468,954 as unsigned integer) are reinterpreted as a floating-point value (1.103469×109) and the resulting 32-bit pattern (0x4E838B33) is written to the destination. The transfer is "correct" per the IEC 61131-3 type system, but not what most engineers expect from a raw memory copy.

Does the same code raise an error on S7-1500 firmware?

Yes — from TIA Portal V13 SP2 onward, the S7-1500 SCL compiler rejects the assignment with the error "Datatype "LReal" cannot be converted implicitly to datatype "DWord" when the destination is a raw DBD address. The S7-1200 compiler still allows it with a warning, so the bug remains portable to the smaller CPU family.

What is the cleanest way to perform a bit-exact 32-bit copy between two DBD addresses?

Declare an AT overlay of type DWORD over the destination tag, then assign the source DBD to the DWORD view. The compiler sees a DWORD → DWORD assignment, generates a single UD (Unconditional Double-word) move, and no conversion is performed. The pattern is supported on every S7-1200 firmware from V4.0 and on every S7-1500 firmware.

Why does assigning the literal 24.7 to %DB1.DBD0 produce a different error than assigning it to a REAL tag?

Numeric literals in SCL default to LREAL (64-bit). When the destination is a REAL tag, the implicit LREAL_TO_REAL conversion is allowed; when the destination is a raw DBD (treated as DWORD), the LREAL_TO_DWORD conversion is not allowed and the compiler raises the error "Datatype "LReal" cannot be converted implicitly to datatype "DWord". Type the literal explicitly (REAL#24.7 or DWORD#16#41C5999A) to avoid the ambiguity.

Can I disable the implicit conversion with a compiler switch?

No. The "IEC checks" property in the SCL block properties does not affect the implicit DINT_TO_REAL cast; it only controls the strictness of warnings/errors for non-IEC constructs (such as direct memory access). Disabling IEC checks to suppress this warning also breaks safety-tooling acceptance and is not recommended. Use one of the five documented workarounds (AT overlay, DWord FB, explicit cast, word-by-word move, or STL MOVE box) instead.

Back to blog