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.
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:
-
Symbol lookup. For every
%DBx.DBByreference, 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. -
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:
- Resolve source:
%DB1.DBD8→ no tag overlap → type isDWORD(signed interpretation:DINT). - Resolve destination:
%DB1.DBD4→ tagvar2 : REAL. - Type-check:
REAL := DWORD→ implicitDINT_TO_REALinsertion (per IEC 61131-3 table 12.6 for SCL). - Generate STL: the compiler emits an
ITD(Integer to Double Integer) followed by aDTR(Double Integer to Real) block before the actualMOVE(or it uses aROUND/CONVcombination 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.
Best Practices for S7-1200 Bit-Level Buffer Operations
-
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 aREALcast from aDWORD-typed tag. -
Use AT overlays for buffers. When a tag of type
REAL,DINT, orINTmust be addressed as raw bits, declare a siblingATview of typeDWORD,WORD, orBYTE. This is the official Siemens-recommended pattern for the S7-1200 family. -
Type all floating-point literals explicitly. Always write
REAL#24.7orLREAL#24.7. The defaultLREALbehavior will break in V13 SP2+ for S7-1500 and is a latent bug on S7-1200. -
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. -
Prefer a single MOVE_BLK / MOVE for bulk operations. The SCL
MOVEkeyword compiles to a singleUD(orUN) and is type-agnostic. It is the only high-level construct that produces bit-exact copies across the entire address space. - 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.
- 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
- Siemens Industry Online Support: SIMATIC S7-1200 Programmable Controller System Manual (entry point for AT-overlay syntax, supported data types, and the cross-reference between tags and absolute addresses).
- TIA Portal V20 help: Explicit conversion of DINT (S7-1500) — reference for the explicit conversion operator table, including the operator that the implicit SCL cast emulates.
-
DINT_TO_REAL function reference (RMC Motion) — cross-vendor example illustrating that the same operator name (
DINT_TO_REAL) is used by other IEC 61131-3 controllers to perform the bit-level reinterpretation we see on the S7-1200. The Siemens behavior is consistent with the IEC standard when both source and target types are exposed as symbols.
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.