Fixing TIA Portal MD200 Double Word Conversion and Overlapping

David Krause14 min read
SiemensTIA PortalTroubleshooting
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

Fixing TIA Portal MD200 Double Word Conversion and Overlapping M-Memory

1. Problem Overview

Engineers programming SIMATIC S7-1200, S7-300, and S7-400 controllers in TIA Portal frequently report that an MD-tag (double word, 4 bytes) returns a nonsensical value after the program is downloaded, even though the source values look correct in the watch table. A typical symptom is the raw bytes of two 16-bit words (e.g., two energy-meter registers, scaled analog values, or counter high/low words) being combined into a double word, but the resulting DINT, DWORD, or REAL does not match the expected engineering value.

Two distinct root causes account for almost every case of this symptom in the field:

  1. Overlapping M-memory: A double word and a word (or two words) were manually placed on the same starting byte by mistake, so writing one tag clobbers the other.
  2. Byte order (endianness): The high word and low word were combined in the wrong order, or the byte swap inside one of the words was not honored when the value is interpreted as IEEE 754 REAL.

The remainder of this reference documents the Siemens S7 memory model, the exact rules for MD200, the differences between DINT, DWORD, and REAL, the diagnostic procedure, and a verified, step-by-step remediation. It also covers the recommended long-term fix: routing all working values into instance or global DB tags instead of the volatile M area.

Safety notice: Before you modify any tag that participates in a live process, place the CPU in STOP or ensure the affected logic is not driving an actuator. Editing M-memory addresses online can cause unpredictable outputs if the tag is used in cyclic OB1 code.

2. Root Cause: Why MD200 Suddenly Returns a Wrong Value

In every S7-1200 / S7-300 / S7-400 CPU, the bit memory area (M area) is byte-addressed. A tag declared as MD200 occupies bytes MB200, MB201, MB202, and MB203. A tag declared as MW200 occupies bytes MB200 and MB201. A tag declared as MW202 occupies bytes MB202 and MB203.

If the programmer manually types MD200 for one tag and MW202 for another tag in the PLC tag table, the two addresses overlap on bytes 202 and 203. TIA Portal does not warn about this overlap because it treats every entry as an independent declaration. The first scan writes the double word, and the next scan partially overwrites the upper two bytes when a separate instruction writes the word at MW202 (or vice versa). The end result is a non-deterministic value that toggles depending on which instruction runs last in OB1.

A second variation of the same fault appears when two adjacent words (MW200 and MW202) are deliberately placed to build a double word, but the destination tag is also placed on the same range, producing a triple overlap. The watch table then shows different values each scan and the conversion to REAL produces garbage.

According to the S7-1200 System Manual and the TIA Portal Programming and Operating Manual, every tag in the M area must be unique at the byte level. There is no automatic compiler check for partial overlap in classic STEP 7 or TIA Portal; the engineer is responsible for the assignment.

3. Siemens S7 Memory Addressing Model

The S7 memory model partitions the CPU work memory and load memory into distinct address areas: inputs (I), outputs (Q), bit memory (M), timers (T), counters (C), and data blocks (DB). Each area is independently byte-addressed. Within each area, the following tag sizes are permitted:

S7 Tag Prefix Size Byte Range for MD200 Typical Use
MB n 1 byte (8 bits) 200, 201, 202, 203 Status byte, handshakes
MW n 1 word (2 bytes) 200-201 and 202-203 16-bit status word
MD n 1 double word (4 bytes) 200-203 32-bit DINT, DWORD, REAL, TIME, DATE, TOD, DTL
DBx.DBBy 1 byte n/a (DB area) Structured data

For the address MD200 in an S7-1200 / S7-1500 CPU, the byte layout is:

  • Byte 200 — bits 24-31 (most significant byte)
  • Byte 201 — bits 16-23
  • Byte 202 — bits 8-15
  • Byte 203 — bits 0-7 (least significant byte)

Two adjacent words used to build a double word (the classic "combine two words to get kWh" pattern) must therefore be placed at MW200 (bytes 200-201) and MW202 (bytes 202-203). Any other combination is an immediate overlap.

The official SIMATIC S7-1200 Programmable Controller System Manual (Siemens support entry 109746818) confirms this byte-level layout in chapter 4, "Memory areas and addressing," and lists the valid tag prefixes and their bit-widths. The same rule applies to the S7-300/400 family described in the S7-300/400 System and Programming manuals.

4. Data Type Semantics: DINT vs DWORD vs REAL

Three 32-bit data types can occupy the four bytes of MD200. They share the same bit layout but interpret the bits completely differently:

Type Bits Range Encoding When to use
DINT 32 -2,147,483,648 to 2,147,483,647 Two's complement signed Signed 32-bit counters, encoder positions, signed math
DWORD 32 0 to 4,294,967,295 Unsigned binary Bit masks, raw register data, unsigned counters
REAL 32 ±3.402823e+38 (IEEE 754 single) 1 sign, 8 exp, 23 mantissa Floating point engineering values (kWh, m³/h, °C)
TIME 32 T#-24d20h31m23s647ms to T#+24d20h31m23s647ms Signed ms IEC timers stored as long value

If a four-byte tag is read as REAL but was originally written as DINT, the resulting floating-point number is almost never what the engineer expects. For example, the DINT value 1000 (16#000003E8) is interpreted as the REAL value 1.262177e-44, an IEEE 754 subnormal. The same value re-declared as REAL yields the valid engineering value of 1.0e+03. Conversely, a REAL value written by an instrument and then read as DINT will appear as a large, oscillating signed integer.

The TIA Portal Programming and Operating Manual (Siemens support entry 109751325) defines the bit layouts in chapter 6, "Data types." The IEEE 754 single-precision encoding is the same as the one standardized in the IEEE 754-2019 standard, which is the de-facto reference for the REAL type on SIMATIC CPUs.

5. Byte Order and Endianness in S7 PLCs

SIMATIC S7 CPUs store multi-byte values in big-endian byte order at the byte level: the most significant byte of a word is at the lower address, and the most significant byte of a double word is at the lowest address. Within a single byte, bit 7 is the MSB and bit 0 is the LSB, identical to the S5 tradition.

That statement looks simple, but two field situations make it confusing:

  1. Two 16-bit words combined to a 32-bit DINT: If the high word is at MW200 and the low word is at MW202, the double word stored at MD200 is (MW200 << 16) OR MW202. If the source device or the field wiring provides the low word at MW200 and the high word at MW202, the engineer must either swap the source assignments or read the bytes individually and rebuild the DINT with the appropriate shift instructions.
  2. REAL values from Modbus, PROFIBUS, or PROFINET devices: Many third-party devices transmit floats in little-endian word order (DCBA) or in mid-big-endian (BADC) byte order. The S7 CPU's native big-endian byte order (ABCD) requires an explicit byte swap before the value is valid as REAL. This is the most common cause of "almost right" engineering values that are off by a factor of 256, 65,536, or scaled wildly.
If the value you see in the watch table is exactly 256×, 65,536×, or 1/256× the expected value, you have a byte-swap fault, not a conversion fault. Fix the swap before changing the data type.

The byte-swap operation is performed in SCL with the standard library function WORD_TO_INT followed by SWAP, or in LAD with the TAW / TAD instructions. The TIA Portal help portal documents these instructions under "Bit logic operations" and "Converter operations."

6. Diagnostic Procedure: Identifying the Overlap

Use the following sequence to confirm that overlapping M-memory is the root cause before making any code change.

  1. Open the PLC tag table for the affected S7-1200 / S7-300 / S7-400 project. Filter the view by the M area.
  2. Sort the table by Address ascending.
  3. Visually inspect every address that begins with M. For each MD, confirm that no other tag touches any of its four bytes.
  4. Open the Watch table (or create one) and add the suspect MD plus every MW and MB in the surrounding 16 bytes. Trigger a single read of each.
  5. Online, set a breakpoint in OB1 at the network that writes the MD. Force a single execution with Monitor with trigger.
  6. Use the Inspector → Cross-references tool (Ctrl+Shift+F) on the suspect MD to confirm which networks read or write it.

For an offline static check, the TIA Portal "Compile and check consistency" action will report inconsistent tag assignments, but it does not catch manual M-area overlaps. Several Siemens knowledge base articles explicitly note that overlap detection for manually entered M addresses is the programmer's responsibility.

7. Step-by-Step Fix: Reassigning MD200 Safely

Use the following procedure, which corresponds to the working solution described by senior practitioners in the SIMATIC community.

  1. Open the PLC tag table in the project tree under "PLC > PLC tags > Default tag table."
  2. Identify every tag that uses any byte between MB200 and MB203 inclusive. Note each name, its data type, and the network where it is referenced.
  3. Delete the tag that uses MD200. Leave a one-line comment above each remaining tag describing its purpose so that the next maintainer can verify the layout.
  4. Open the network that previously wrote to MD200. The tag symbol will appear in red (unresolved). Right-click the tag operand, select "Define tag," and let TIA Portal assign the next free M address that can accommodate a 4-byte double word. For example, if MB196 through MB199 are free, TIA Portal will assign MD196 automatically.
  5. If the value being produced is itself the result of combining two adjacent words, declare the source words as MW_High and MW_Low with explicit offsets (e.g., MW_Low = MW196 and MW_High = MW198) and rebuild the DINT with the standard SCL pattern below.
  6. Compile the project. Resolve any remaining unresolved tag errors in the same pass.
  7. Download the hardware configuration and the software to the CPU in STOP, then start the CPU.

7.1 SCL Pattern: Build a DINT from Two Words

// High word at MW200, low word at MW202
// Result stored in MD180 (free address)
"MD180" := DWORD_TO_DINT( SHL( WORD_TO_DWORD("MW200"), 16 ) OR WORD_TO_DWORD("MW202") );

7.2 SCL Pattern: Convert the Combined DINT to REAL

// If the source instrument returns the value as a scaled DINT (e.g., 1 LSB = 0.1 kWh)
"MD_RealValue" := DINT_TO_REAL("MD180") / 10.0;

If the original MD200 is itself a REAL (for example, a kWh value coming directly from a Modbus energy meter), reassign it as REAL in the tag table rather than DINT. The CPU will store the four bytes correctly and the watch table will display the engineering value without a manual conversion. The TIA Portal "Define tag" dialog allows you to pick the data type and the address simultaneously.

8. Best Practice: Use DB Tags Instead of M-Memory

The M area in SIMATIC S7 is intended for hand-shake flags, temporary scratch storage, and small amounts of bit memory. It is volatile (cleared on power cycle unless configured as retentive), it is not structured, and it does not benefit from the version-tracking or download-coherence of data blocks. Every experienced TIA Portal engineer follows the rule: never use the M area for production data.

For application values such as the kWh register being combined in this scenario, create a global data block:

  1. Project tree → "PLC > Program blocks > Add new block → Data block."
  2. Name the DB DB_ProcessData, uncheck "Optimized block access" only if you have external devices that need the absolute byte layout, otherwise leave it optimized for S7-1200/1500.
  3. Declare the high and low words as separate tags, e.g., kWh_High : Word; and kWh_Low : Word;, and the combined value as kWh_Real : Real;.
  4. Use symbolic access everywhere ("DB_ProcessData".kWh_Real in SCL or the symbolic operand in LAD/FBD). The compiler will catch every overlap automatically.

Optimized data blocks also gain symbolic-only access, automatic remanence settings, and download-without-reinitialization on S7-1500. These advantages do not exist in the M area.

9. Verification and Monitoring

After the fix, perform the following verification steps before returning the system to production:

  1. Open the watch table and add the new MD address, the two source words, and the resulting REAL value. Force the CPU to STOP, write known test values to the source words, and read the MD back. Confirm the bit pattern is consistent with the engineering value.
  2. Toggle the CPU to RUN. Monitor the value live for at least one full process cycle. The display should be stable and free of the oscillating behavior that characterized the original fault.
  3. Use the cross-reference tool (Ctrl+Shift+F) to confirm that no other tag or block references the old MD200 address. A "no references" result confirms the cleanup is complete.
  4. Save the project, run a full "Compile → Software (rebuild all)" pass, and archive the project as a baseline.
  5. Document the change in the project's change log: old address, new address, reason, and the engineer who approved the change.

10. Edge Cases and Field-Proven Caveats

  • Retentive M-memory: M addresses can be configured as retentive in the CPU properties under "Memory > Retentive memory areas." If MD200 was declared retentive, deleting and recreating the tag at a new address will not preserve the value at power-up. Move any required retentive values into a retentive DB first.
  • Indirect addressing: Code that uses pointer arithmetic on MD (e.g., P#MD200 in any DB block) will break silently if the address changes. Search for P#M in all sources after the move.
  • HMI tag linkage: WinCC Professional / Comfort Panels store the absolute address. Re-link the HMI tag to the new DB path, or the faceplate will display zero.
  • S7-1500 symbolic-only M: S7-1500 firmware V2.0 and later allows the M area to be used symbolically from a global M-DB. If your project uses that feature, you may be seeing an overlap at the DB level rather than the M level. Open the global M-DB and check the offsets.
  • Firmware-specific REAL behavior: S7-1200 firmware V4.0 and later handle NaN and ±Inf in REAL according to IEEE 754. Earlier firmware V2.x produced zero in place of NaN. If the displayed value is always 0.0 and the source bytes are non-zero, check the firmware version in the device properties.
  • Online watch vs. program execution: The watch table can briefly display stale data while the program is being downloaded. Always do the verification in a fresh online session after the download finishes.

11. Quick-Reference Parameter Map

Concept Address Example Byte Layout Common Fault
Double word MD200 MB200 MB201 MB202 MB203 Overlap with MW202 or MB202-MB203
Adjacent words MW200, MW202 MB200-MB201, MB202-MB203 Wrong high/low word order
Byte view MB200-MB203 4 separate bytes Re-typed as MD after the fact
REAL in DB DB100.DBD0 4 bytes inside DB Endianness mismatch with field device
DINT vs DWORD MD300 4 bytes, same bits Sign bit misread

12. References to Official Documentation

FAQ

Why does my MD200 value look correct in the tag table but wrong in the program?

The tag is most likely overlapping with another manually-entered M address. Open the PLC tag table, sort by address, and confirm that no other tag touches bytes MB200-MB203. Reassign the conflicting tag to a free address or convert all working values to a global DB.

How do I combine two 16-bit words into a 32-bit DINT in TIA Portal?

Use the SCL expression SHL(WORD_TO_DWORD(MW_High),16) OR WORD_TO_DWORD(MW_Low). Ensure MW_High and MW_Low are at adjacent even addresses that do not overlap with any other tag, and store the result in a free MD or in a Real-tag inside a DB.

MD200 returns 0.0 even though the source bytes are non-zero — what is wrong?

The data type declaration is almost certainly DINT, not REAL. Re-declare the tag as REAL in the PLC tag table, or convert explicitly with DINT_TO_REAL in SCL. Also confirm the CPU firmware supports IEEE 754 NaN and infinity correctly (S7-1200 V4.0+).

My value is exactly 256× the expected value — is that a wiring issue?

No, it is a byte-order issue. The device supplying the value uses a different endianness than the S7 CPU. Apply the SWAP or TAD instruction to the four bytes before treating the tag as REAL or DINT. The TIA Portal converter operations help page documents the byte-swap instruction.

Should I keep using M-memory for my process values, or switch to a DB?

Switch to a global data block. The M area is volatile, unstructured, and offers no compiler-level overlap check. A global DB (optimized on S7-1200/1500) gives symbolic access, automatic remanence, version tracking, and compile-time overlap protection, and it is the recommended pattern in the SIMATIC S7-1200 System Manual.

Back to blog