Reading REAL Values from S7-400H DB via Modbus TCP/IP CP 443-1

David Krause15 min read
ModbusSiemensTutorial / 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

Reading REAL Values from S7-400H DB via Modbus TCP/IP CP 443-1

When a Siemens S7-400H (H-System) is the Modbus TCP/IP server, an external client (SCADA, HMI, OPC UA gateway, or third-party PLC) can only read 16-bit holding registers. A 32-bit REAL value in a Data Block does not map to one Modbus register - it must be split into two consecutive 16-bit words, transmitted, and reassembled in the application layer. This article documents the exact wire format, the CP 443-1 Modbus configuration, the word-order pitfall that causes every wrong-value symptom in the field, and the STEP 7 STL swap block that resolves it.

The Modbus Application Protocol V1.1b3 published by the Modbus Organization defines a register as a 16-bit quantity and does not standardize byte or word order for multi-register values. Word order is an application-layer contract between server and client.

1. Why Modbus Cannot Carry a REAL Directly

Modbus is fundamentally a 16-bit protocol. The original Modicon specification (1979) and the modern Modbus Application Protocol V1.1b3 define four data primitives:

  • Coil (1 bit, read/write)
  • Discrete Input (1 bit, read-only)
  • Holding Register (16 bits, read/write)
  • Input Register (16 bits, read-only)

Function codes FC 03 (Read Holding Registers), FC 04 (Read Input Registers), FC 06 (Write Single Register), FC 16 (Write Multiple Registers), and FC 23 (Read/Write Multiple Registers) all transport 16-bit words. A 32-bit IEEE 754 single-precision REAL therefore occupies exactly two consecutive Modbus registers, and a 64-bit LREAL occupies four.

This is the source of every "I read 0.0" or "I read garbage" symptom. The PLC stores the REAL correctly in the DB; the CP transmits the two halves correctly; but the client interprets the two halves in the wrong order, or treats them as separate INT values.

2. IEEE 754 Single-Precision (32-bit) Format

The S7-400H REAL data type is an IEEE 754 single-precision float. The IEEE Std 754-2008 layout is:

Bit 31 Bits 30-23 Bits 22-0
Sign (0=+, 1=-) Exponent (bias 127) Mantissa (implicit leading 1)

Example reference values for field verification:

REAL Hex (32-bit) Word 1 (high) Hex Word 0 (low) Hex
0.0 0x00000000 0x0000 0x0000
1.0 0x3F800000 0x3F80 0x0000
123.45 0x42F6E666 0x42F6 0xE666
-1.0 0xBF800000 0xBF80 0x0000
+Inf 0x7F800000 0x7F80 0x0000

When the S7-400H stores a REAL at DB100.DBD4, the four bytes are laid out in little-endian byte order in physical memory. In the Modbus holding register space, this becomes:

  • Modbus register N = bytes 0-1 (low-address) = low 16 bits of the REAL
  • Modbus register N+1 = bytes 2-3 (high-address) = high 16 bits of the REAL

3. S7-400H Hardware, CP 443-1, and Required Firmware

The S7-400H redundant system (per the Siemens S7-400H Automation System Manual) uses CPUs such as CPU 412-3H, CPU 414-4H, CPU 416-4H, and CPU 417-4H on an SIMATIC UR2-H rack. Modbus TCP/IP server functionality is provided by the CP 443-1 Communication Processor, not the CPU itself.

Verified CP 443-1 part numbers supporting the Modbus/TCP server option:

Article Number Variant Min Firmware Modbus/TCP HSP
6GK7 443-1EX30-0XE0 CP 443-1 (4-port switch) V3.0 Required
6GK7 443-1GX30-0XE0 CP 443-1 IT V3.0 Required
6GK7 443-1UX00-0XE0 CP 443-1 OPC UA V3.0 Required
6GK7 443-1EX20-0XE0 CP 443-1 (legacy) V2.x Not supported

Older CP 443-1 EX20/GX20 modules do not support the Modbus TCP/IP server option and cannot be used for this application. Confirm the firmware version of the installed CP in STEP 7 under PLC → Module Information before commissioning.

The Modbus/TCP server functionality is delivered via the Siemens HSP (Hardware Support Package) "Modbus/TCP PN-CPU" or "Modbus/TCP CP" depending on STEP 7 version. Install the HSP in STEP 7 V5.5 SP4 or later (or the equivalent package in TIA Portal V14+). The HSP adds the partner type "Modbus TCP server" to NetPro and the corresponding configuration dialogs.

4. Word Order: The Root Cause of Wrong REAL Readings

Three word-order conventions are seen in production Modbus TCP/IP deployments:

  1. Low word first (Siemens CP 443-1 default, Modicon TSX ETY): register N = low 16 bits, register N+1 = high 16 bits. Byte order within each register is big-endian (network byte order) for the wire.
  2. High word first (some Modicon Unity PRO mappings, some SCADA drivers): register N = high 16 bits, register N+1 = low 16 bits.
  3. Byte-swapped within word (rare, some Asian vendors): the bytes inside each 16-bit register are reversed on the wire.

When the client expects convention (2) but the S7-400H CP 443-1 sends convention (1), the decoded IEEE 754 value is:

  • Zero, Inf, or NaN for most values, because the exponent field (which carries the magnitude information) is replaced by the mantissa and vice versa.
  • Sign flip for some values, because the sign bit moves from bit 31 to bit 15 (interpreted as a negative INT or as part of the mantissa).
  • Wildly wrong magnitude, often 2^16 or 2^-16 of the correct value.
A single 16-bit register that is mis-ordered cannot be salvaged in the client without an explicit swap step. The CP 443-1 will always send the same wire bytes; the fix must be on the side that misinterprets them, or a swap block in the S7-400H program before the data is exposed to the CP.

5. Data Block to Modbus Register Mapping

Configure the CP 443-1 Modbus server in NetPro to map a contiguous range of the S7-400H memory (DB or Merker/Prozessabbild) to Modbus Holding Registers. The default starting address is 40001 (function code 3 offset 0). Example mapping for a 4-channel pressure / temperature block:

S7-400H Address IEC Type Bytes Modbus Register (FC 03) Function Code
DB100.DBW0 INT 2 40001 FC 03 / FC 06
DB100.DBD2 REAL 4 40002 (low) + 40003 (high) FC 03
DB100.DBD6 REAL 4 40004 (low) + 40005 (high) FC 03
DB100.DBD10 REAL 4 40006 (low) + 40007 (high) FC 03
DB100.DBW14 WORD 2 40008 FC 03 / FC 16

The CP 443-1 transmits Word 0 first (low word of the REAL) and Word 1 second (high word) for the default Siemens Modbus mapping. If the SCADA or third-party client expects high word first, swap the words on either side as described in sections 8 and 9.

6. Configuring the CP 443-1 Modbus TCP/IP Server

  1. Open the S7 project in STEP 7 V5.5 (or TIA Portal with the appropriate HSP).
  2. Open NetPro and right-click the CP 443-1 in the rack.
  3. Select Insert New Connection → partner type Modbus TCP server.
  4. Assign the CP IP address (e.g., 192.168.0.10) and TCP port 502 (default Modbus port).
  5. Open the CP's Properties → Modbus configuration dialog.
  6. Define the data area: starting address in the DB (e.g., DB100, byte 0), length in bytes, mapping to Modbus holding register base 40001.
  7. Set the byte/word order to Low word first (default) or High word first depending on the client expectation.
  8. Compile and download the configuration to the CP 443-1 (a full download may be required to activate the Modbus task).
  9. Cycle power on the CP if the firmware/HSP option is being activated for the first time.
The CP 443-1 maintains its configuration in non-volatile flash. A power cycle is required after a firmware change or first-time HSP activation. The S7-400H CPU continues to run during CP power-down, but Modbus clients will receive connection refused (TCP RST) until the CP is back online.

7. Reading REAL: Step-by-Step Procedure

7.1 Prerequisites

  • S7-400H with CPU 41x-4H, firmware V6.0 or later
  • CP 443-1 EX30/GX30 with firmware V3.0 or later
  • STEP 7 V5.5 SP4 (or TIA Portal equivalent) with Modbus/TCP HSP installed
  • Target Data Block (DB) compiled and downloaded to the S7-400H
  • Any conformant Modbus TCP/IP client (CAS Modbus Scanner, Modbus Poll, openMUC, libmodbus-based app, or another PLC)

7.2 Create the Data Block

In STEP 7, create DB100 with the following structure (Symbol Table or absolute addresses):

DATA_BLOCK DB100
STRUCT
   Pressure     : REAL;    // 4 bytes, DBD0-DBD3
   Temperature  : REAL;    // 4 bytes, DBD4-DBD7
   Setpoint     : REAL;    // 4 bytes, DBD8-DBD11
   Status       : WORD;    // 2 bytes, DBW12
   ErrorCode    : INT;     // 2 bytes, DBW14
END_STRUCT
END_DATA_BLOCK

7.3 Configure CP 443-1 Modbus Mapping

Map DB100 byte 0 onward to Modbus holding register 40001 with the byte/word order matching the client.

7.4 Verify with a Modbus Master Tool

Use a Modbus TCP master to read 2 registers starting at register 1 (the REAL at DB100.DBD2 = Pressure):

MBAP Header: TxID=0001, ProtoID=0000, Length=0006, UnitID=01
PDU:         Function=03, StartHi=00, StartLo=01, QtyHi=00, QtyLo=02
Expected PDU response: 01 03 04 [B0 B1 B2 B3] [CRC CRC]

Capture the four response bytes and decode manually:

  • If 123.45 is the value in the DB, expected hex (little-endian word) is E6 66 42 F6 on the wire (4 bytes returned by FC 03 as a single 4-byte data block per the spec, but each pair of bytes is a Modbus register).
  • Reassemble: low word = 0x66E6, high word = 0xF642. Combined 32-bit = 0xF64266E6, which in IEEE 754 = 123.45 (verify with floating-point calculator).

7.5 Implement Word-Swap on the Server Side (STEP 7 STL)

If the client expects high word first, swap the words inside the S7-400H program before the CP reads them. Add a separate "shadow DB" that holds the swapped copy:

// OB1 cycle - swap REAL values for client readability
// Assume DB100 contains native REAL, DB200 contains swapped copy

      L     DB100.DBD    0       // Load Pressure (native low-word-first)
      T     DB200.DBD    0
      TAW                      // Swap bytes within low word (Siemens TAW swaps bytes, not words)

      L     DB100.DBD    4       // Load Temperature
      T     DB200.DBD    4
      TAW

// For FULL word swap (low word <-> high word), use:
      L     DB100.DBW    0       // Low word of Pressure
      T     DB200.DBW    2       // High word of swapped copy
      L     DB100.DBW    2       // High word of Pressure
      T     DB200.DBW    0       // Low word of swapped copy
TAW (Tausche Worte / Swap Bytes within Word) does NOT swap words; it swaps bytes within a 16-bit word. To swap the order of the two 16-bit words that make up a 32-bit REAL, use the manual two-L/T sequence above, or the SWAP_I/DWORD function in the IEC 61131-3 standard library.

7.6 Implement Word-Swap on the Client Side

If the client is a C/C++ application using libmodbus or a similar library:

// C code - reconstruct REAL from two Modbus holding registers
// Assuming little-endian host (x86, ARM Cortex, etc.)
#include <stdint.h>
#include <string.h>

float modbus_read_real(uint16_t reg_lo, uint16_t reg_hi) {
    // Default Siemens CP 443-1: reg_lo is the low 16 bits of the REAL
    uint32_t combined = ((uint32_t)reg_hi << 16) | reg_lo;
    float value;
    memcpy(&value, &combined, sizeof(float));
    return value;
}

float modbus_read_real_swap(uint16_t reg_lo, uint16_t reg_hi) {
    // For clients expecting high word first
    uint32_t combined = ((uint32_t)reg_lo << 16) | reg_hi;
    float value;
    memcpy(&value, &combined, sizeof(float));
    return value;
}

On a Modicon client (Unity PRO / EcoStruxure Control Expert), use the following Structured Text:

// Read 2 words from S7-400H CP 443-1 via Unity Modbus master
arrWords[0] := READ_HOLDING_REGISTERS(Slot := 0, Addr := 1, Qty := 2);
arrWords[1] := READ_HOLDING_REGISTERS(Slot := 0, Addr := 2, Qty := 1);

// If high-word-first expected:
arrSwapped[0] := arrWords[1];
arrSwapped[1] := arrWords[0];

rPressure := REAL_FROM_WORDS(arrSwapped[0], arrSwapped[1]);

8. Verification Procedure

  1. Force a known REAL value in the S7-400H DB using a VAT (Variable Table) in STEP 7: e.g., DB100.DBD0 = 123.45 (use the float entry in the VAT, not a hex value).
  2. Connect the Modbus master to the CP 443-1 IP and port 502.
  3. Issue FC 03 with starting register 1 and quantity 2.
  4. Capture the raw 4-byte response and verify hex against the IEEE 754 reference table in section 2.
  5. Confirm the client's decoded float matches 123.45 within 0.001.
  6. Test with 0.0, -1.0, 1.0, and a value near +Inf boundary (e.g., 1.0E+38) to verify sign and exponent handling.
  7. Test with at least one negative REAL to verify the sign bit is at bit 31 of the reassembled 32-bit value, not bit 15.

9. Troubleshooting Matrix

Symptom Likely Cause Action
Client always reads 0.0 Word order mismatch; low/high words swapped Swap the two 16-bit words on client or server side; verify with 1.0 (0x3F800000)
Value reads as +Inf or NaN Words combined in wrong order; exponent bits replaced by mantissa Confirm word order; capture hex response and decode manually
Off by factor of 256 or 65536 Only one word read; client misuses FC 03/04 quantity Set Quantity = 2 for one REAL, 4 for two, etc.
Value appears negated Sign bit (bit 31) interpreted as part of exponent or mantissa Confirm 32-bit reassembly, not 16-bit INT interpretation
Intermittent connection drops CP 443-1 keep-alive timeout too low; Modbus watchdog Increase Watchdog in CP configuration; set TCP keep-alive on client
FC 03 returns exception 02 (Illegal Address) DB number or offset not mapped in CP 443-1 Modbus config Reconfigure Modbus data area in CP, recompile, download to CP
FC 03 returns exception 03 (Illegal Value) Quantity not 1, 2, or > 125 words Set Quantity to 2 for one REAL; 4 for two REALs, etc.
Value changes when CPU switches to backup S7-400H redundancy not synchronized for the DB area Verify DB100 is in the synchronized area; check LINK and RES redundant I/O
Hex response correct but client decodes as little-endian DWORD Client assumes 32-bit register; misuses byte order Force the client to read 2x 16-bit and combine in client code
One REAL is correct, next REAL is shifted by 1 word DB has an INT between REALs that was not skipped in mapping Reconcile DB byte layout with CP mapping table; use a continuous REAL block

10. IEEE 754 Edge Cases in Modbus Transports

Some REAL values round-trip incorrectly through 16-bit Modbus registers when one of the two words is dropped, masked, or out of order. The following edge cases should be explicitly tested in commissioning:

  • 0.0 (0x00000000): all bits zero. Reads correctly through any byte or word order, so a zero value is not a good test for word order.
  • -0.0 (0x80000000): sign bit set, all others zero. Reads correctly only if the sign bit ends up in bit 31 after reassembly.
  • +Inf (0x7F800000) and -Inf (0xFF800000): if the words are swapped, these become NaN (0x7F80xxxx or 0xFF80xxxx with non-zero mantissa), which most clients display as an error or zero.
  • NaN (any 0x7Fxxxxxx with mantissa != 0): bit pattern changes non-deterministically under word swap; a stable NaN cannot be guaranteed across the wire.
  • Denormals (exponent = 0, mantissa != 0): the smallest non-zero REALs. If either 16-bit word is misread as zero, the value collapses to 0.0.

Always validate the installation with a non-zero, non-Infinity, non-NaN test value (for example, 123.45) before declaring the Modbus path operational.

11. Function Code Reference for REAL Traffic

Function Code Mnemonic Use for REAL Notes
01 Read Coils No 1-bit data only
02 Read Discrete Inputs No 1-bit data only
03 Read Holding Registers Yes - read 2+ consecutive Primary code for DB-served REAL values
04 Read Input Registers Yes - read 2+ consecutive Used when source is PIW (analog input image)
05 Write Single Coil No 1-bit data only
06 Write Single Register No REAL requires 2 registers; use FC 16
15 (0F hex) Write Multiple Coils No 1-bit data only
16 (10 hex) Write Multiple Registers Yes - write 2+ consecutive Standard write path for one or more REALs
23 (17 hex) Read/Write Multiple Registers Yes Atomic read+write; rare in S7-400H CP 443-1

12. S7-400H Redundancy Considerations

Because the S7-400H is a hot-standby system with two CPUs running in parallel, the DB area mapped to the CP 443-1 must be part of the synchronized data. Siemens documentation specifies that DBs in the "non-synchronized" or "CPU-local" area are not guaranteed to be consistent across a failover. If the CP is wired to the primary rack only, it will lose connection for the duration of the switchover (typically < 100 ms). If the CP is wired to both racks (redundant CP configuration), the Modbus client should see no interruption provided the keep-alive timeout is longer than the switchover time.

Recommendations:

  • Map only synchronized DBs to the Modbus server.
  • Configure both CPs in redundant mode if 100% Modbus availability is required.
  • Set client TCP keep-alive to at least 1000 ms to absorb a single switchover.
  • Use Modbus function code 03 (read-only) for control-critical process values to avoid split-brain writes during failover.

Why does my Modbus client always read 0.0 for every REAL value?

The most common cause is the client assembling the two 16-bit registers in the wrong order. The Modbus Application Protocol V1.1b3 does not standardize word order for multi-register values. Swap the low and high words on the client side, or confirm the CP 443-1 Modbus configuration is set to the byte/word order your client expects. Verify with a known value like 1.0 (0x3F800000) before commissioning.

Can I read or write a REAL with Function Code 06 (Write Single Register)?

No. FC 06 writes a single 16-bit register. To write a REAL, use FC 16 (Write Multiple Registers) with a quantity of 2, sending both the low and high 16-bit words in a single transaction. Reading a REAL also requires FC 03 or FC 04 with a quantity of 2.

What is the difference between Function Code 03 and Function Code 04 for REAL values?

Function Code 03 reads Holding Registers (read/write data). Function Code 04 reads Input Registers (read-only data, typically mapped from analog input process image). Both return 16-bit words. The S7-400H CP 443-1 with the Modbus/TCP HSP typically maps user-configured DB areas to FC 03; FC 04 is used when the source is a PIW (Periphery Input Word) or directly from the analog input module.

How do I swap the word order of a REAL in STEP 7 STL?

Use a manual two-load/two-transfer sequence to move the low 16-bit word to the high position and the high word to the low position in a shadow DB. The TAW (Swap Bytes within Word) instruction swaps bytes inside a single 16-bit word, not words across a 32-bit REAL. The example STL in section 7.5 shows the correct sequence. Alternatively, use the SWAP_I / SWAP_DWORD function from the IEC 61131-3 standard library on a Modicon client.

Does the CP 443-1 need a special firmware option for Modbus TCP/IP server mode?

Yes. The Modbus TCP/IP server functionality on the CP 443-1 requires the Siemens HSP (Hardware Support Package) for "Modbus/TCP CP" and a CP 443-1 EX30 or GX30 with firmware V3.0 or later. Older CP 443-1 EX20/GX20 modules do not support the Modbus TCP/IP server function and must be replaced. After installing the HSP, cycle power on the CP to activate the new functionality.

Back to blog