S7-1500 Modbus_Master: Reading Holding Registers Past 40001

David Krause13 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

Overview

The Siemens S7-1500 Modbus_Master instruction does not accept raw Modbus protocol addresses directly. Instead, it uses a PLC-style register notation where the high digit of the address range identifies the function: 0xxxx for coils, 1xxxx for discrete inputs, 3xxxx for input registers, and 4xxxx for holding registers. The block internally subtracts the leading offset (40001, 30001, 10001, or 00001 depending on MODE) and forwards a standard Modbus Application Protocol (MBAP) PDU on the serial line.

This design lets an engineer read any holding register—including a register at protocol address 100—without breaking the library's MODE contract. The trade-off is that you must add the appropriate offset to the protocol address before placing it in DATA_ADDR. For Holding Registers this means DATA_ADDR = protocol_address + 40001.

A common confusion is reading the help text literally. The block description states that function code 03 requires an address between 40001 and 49999. That range refers to the Siemens register notation, not the underlying Modbus protocol address. Adding 40001 to the desired Modbus address is the correct way to address registers that fall below 40001 in the Siemens notation.

Modbus Address Models: Protocol vs. PLC Notation

Modbus defines four primary object types, each with its own function code and address space. The Modbus Organization's Introduction to Modbus documents these as coils, discrete inputs, input registers, and holding registers, with the PDU address running from 0 to 65535. Many PLC vendors, however, expose these as 0xxxx, 1xxxx, 3xxxx, and 4xxxx, where the leading digit identifies the object and the trailing digits are offset by 1 from the protocol address. The Software Toolbox analysis of Modbus offset vs. addressing explains why this layer of interpretation exists: it lets a single library handle FC01, FC02, FC03, and FC04 by reusing the same address field with different leading digits.

Siemens notation Object Modbus FC (read) Modbus FC (write) PDU address range
0xxxx Coil (bit) 01 05, 15 0 – 65535
1xxxx Discrete input (bit) 02 — 0 – 65535
3xxxx Input register (word) 04 — 0 – 65535
4xxxx Holding register (word) 03 06, 16 0 – 65535

The numeric portion of the Siemens notation equals PDU address + 1. So a Modbus holding register at protocol address 100 appears as 40101 in Siemens notation, a register at protocol address 0 appears as 40001, and a register at protocol address 9998 appears as 49999.

Prerequisites

Before configuring the Modbus_Master block, verify that the following hardware and software items are in place.

  • CPU: S7-1500 (any firmware that supports the Modbus RTU library, generally V2.0 and later for the standard Modbus library, V2.5 and later for the "MODBUS PN" library).
  • Communication module: A point-to-point module that supports Modbus RTU master. The CM 1541-1 (6GK7541-1AB00-0AB0) and ET 200SP CM PtP (6ES7137-6AA00-0BA0) are the standard options for S7-1500 serial Modbus. The S7-1500 CPU serial interface on certain compact CPUs can also be used if firmware supports it.
  • Engineering software: TIA Portal V16 or later (V17/V18 recommended for current firmware). The MODBUS library is included with TIA Portal; no additional install is required.
  • Wiring: RS-485 two-wire or four-wire twisted pair with termination resistors (typically 120 Ω) at both cable ends, plus a bias network where required by the slave device. Maximum cable length is 1200 m at 9600 baud per the EIA-485 standard, with derating above 19200 baud.
  • Slave documentation: Map of the slave's Modbus address map, including the protocol address (PDU offset) and the data type (INT, UINT, REAL, BOOL, etc.) for each register.

Modbus_Master Block Configuration

The Modbus_Master instruction is found in TIA Portal under Instructions > Communication > MODBUS or in the project library once the MODBUS library has been added. Drop the FB into a cyclic OB (typically OB1) and create an instance data block. The instance DB holds the working state, request parameters, and diagnostics for each call.

The block's input interface is the same across all S7-1500/1200 Modbus RTU master implementations:

Input Type Description
REQ BOOL Rising edge triggers a new transaction.
MB_ADDR USINT Modbus slave address (1–247).
MODE USINT Function class and address range (see MODE table below).
DATA_ADDR UINT Register address in Siemens notation (e.g., 40101 for holding register at PDU 100).
DATA_LEN UINT Number of coils/registers to read or write (1–125 words, 1–2000 bits).
DATA_PTR VARIANT Pointer to a tag or DB area in the PLC where the data is read into or written from.

The output interface provides the standard DONE, BUSY, ERROR, and STATUS signals. STATUS contains the Modbus exception code, the Siemens error class, or the protocol-level return code. Always evaluate ERROR and STATUS on the falling edge of BUSY before issuing a new request.

MODE Parameter Reference

The MODE input selects the function code and the address range the block will use to interpret DATA_ADDR. Use the following reference for all standard Modbus RTU master operations on the S7-1500.

MODE Function code Operation Address range (Siemens notation) Offset to subtract from DATA_ADDR
0 FC 03 Read Holding Registers 40001 – 49999 40001
1 FC 01 Read Coils 00001 – 09999 00001
2 FC 02 Read Discrete Inputs 10001 – 19999 10001
4 FC 04 Read Input Registers 30001 – 39999 30001
5 FC 05 Write Single Coil 00001 – 09999 00001
6 FC 06 Write Single Register 40001 – 49999 40001
15 FC 15 Write Multiple Coils 00001 – 09999 00001
16 FC 16 Write Multiple Registers 40001 – 49999 40001

Each MODE value commits the block to a specific function code and a specific address base. The block does not accept an address range that conflicts with the selected MODE. If DATA_ADDR is outside the listed range, the block returns STATUS 0x80C8 (invalid parameter) without placing a frame on the wire.

Address Translation: The 40001 Offset Rule

To read a Modbus holding register at protocol address 100 on the wire, use MODE = 0 and set DATA_ADDR = 100 + 40001 = 40101. The block performs the offset internally:

  1. Inspects MODE = 0 and selects FC 03 (Read Holding Registers).
  2. Reads DATA_ADDR = 40101 and subtracts 40001 to obtain PDU address 100 (0x0064).
  3. Encodes the request as slave_id | 0x03 | 0x00 0x64 | quantity | CRC_lo | CRC_hi.
  4. Transmits the frame via the configured CM 1541 / CM PtP port.

For a register at protocol address 0, use DATA_ADDR = 40001. For protocol address 9998, use DATA_ADDR = 49999. The general formula is:

DATA_ADDR = protocol_address + base_offset

where base_offset is 40001 for holding registers, 30001 for input registers, 10001 for discrete inputs, and 00001 for coils. The block adds no implicit offset of its own; the +1 in the Siemens notation is what brings protocol address 0 to 40001.

The block accepts a 16-bit unsigned DATA_ADDR in the Siemens notation. The valid range for MODE = 0 is 40001 to 49999, which corresponds to PDU addresses 0 to 9998. Holding registers with PDU addresses 9999 to 65535 are not reachable through this MODE under the standard Modbus library. To address these, use the extended MODBUS_PN library or switch to Modbus TCP, which carries the full 16-bit address space in the MBAP header.

Serial Frame Construction

To verify the configuration, examine the bytes that appear on the RS-485 bus. For the example of slave 0x65 (decimal 101), MODE = 0, DATA_ADDR = 40101, DATA_LEN = 2, the transmitted request frame is:

65 03 00 64 00 02 8D F0
Byte Hex Decimal Meaning
1 65 101 Slave address (MB_ADDR)
2 03 3 Function code 03 (Read Holding Registers)
3 00 0 Starting address high byte (PDU = 100 = 0x0064)
4 64 100 Starting address low byte
5 00 0 Quantity high byte (2 = 0x0002)
6 02 2 Quantity low byte
7 8D 141 CRC-16 low byte (Modbus polynomial 0xA001, init 0xFFFF)
8 F0 240 CRC-16 high byte

The CRC is computed over bytes 1 through 6 with the standard Modbus polynomial and transmitted low-byte first. The 0x8DF0 value matches the field report and is the expected result for the listed PDU and quantity. Capture the bus with a Modbus analyzer (such as a TAP with Wireshark dissector, or a hardware protocol analyzer) to confirm the wire format during commissioning.

The expected response frame for a successful read of two 16-bit values is:

65 03 04 HI1 LO1 HI2 LO2 CRC_LO CRC_HI

where 04 is the byte count, and the four data bytes are the high/low words of the two registers. The block places these into the DATA_PTR tag in the order they appear on the wire (low word first for INT, REAL, etc., per S7-1500 little-endian byte order).

Verification and Diagnostics

Use the following sequence to confirm that the Modbus_Master call is producing the correct frames and receiving valid responses.

  1. Set MB_ADDR, MODE, DATA_ADDR, DATA_LEN, and DATA_PTR in the call interface. Connect DATA_PTR to a structured tag (e.g., "Data".Holding[0]) sized to DATA_LEN words for reads, or pre-loaded for writes.
  2. Trigger REQ with a single-shot rising edge. Avoid pulsing REQ at the OB1 cycle rate; the block ignores new edges while BUSY is set.
  3. Monitor BUSY, DONE, ERROR, and STATUS in the instance DB. Wait for BUSY = 0 before reading the result or issuing the next request.
  4. Inspect the live data area pointed to by DATA_PTR. For reads, the values update only on the cycle where DONE becomes TRUE.
  5. Cross-check by capturing the wire with a protocol analyzer. The transmitted frame should match the byte sequence predicted by the MODE/DATA_ADDR/DATA_LEN inputs, and the slave's response should arrive within the configured response timeout (default 2000 ms in the CM 1541 configuration).

If ERROR = TRUE, evaluate STATUS against the standard error classes:

STATUS Meaning Likely cause
0x80C8 Invalid parameter DATA_ADDR outside the range for the selected MODE; DATA_LEN too large; DATA_PTR points to a tag that is too small.
0x80D1 Response timeout No response from the slave within the configured timeout. Check baud, parity, slave address, wiring, and termination.
0x80D2 Frame error CRC mismatch, framing error, parity error. Check cable length, baud rate, and electrical noise.
0x80D4 Modbus exception from slave Read STATUS low byte for the exception code: 01 (illegal function), 02 (illegal data address), 03 (illegal data value), 04 (slave device failure), 06 (slave device busy), 0A (gateway path unavailable), 0B (gateway target no response).
0x80D5 Port not ready The CM 1541 / CM PtP port is not configured or is in a different state. Verify the port configuration in the device properties.

Common Pitfalls and Error Codes

Several configuration mistakes reproduce the same symptom—STATUS = 0x80C8 or no response from the slave. The most frequent field issues are listed below with their distinguishing indicators.

  • Off-by-one in DATA_ADDR: Using 40100 instead of 40101 reads PDU address 99 instead of 100. The block will not flag this as an error because 40100 is a valid Siemens holding register address. Always confirm the slave's documented PDU address and add 40001 explicitly.
  • Wrong MODE selected: Using MODE = 4 (Input Registers, FC 04) with a 4xxxx address makes the block interpret DATA_ADDR as 30001-based. The wire will show FC 04 instead of FC 03, and the slave will return exception 01 (illegal function) if it does not support FC 04. The block itself does not reject the call until the slave rejects it.
  • DATA_LEN overflow: For FC 03 and FC 04, the maximum is 125 words per the Modbus specification. For FC 16, the maximum is 123 words (the byte count must fit in one byte: 2 * 123 = 246 ≤ 255). The block returns 0x80C8 for over-long requests.
  • Byte order mismatch: The S7-1500 is little-endian. A 32-bit REAL at holding register 100 is stored as register 100 (low word) and register 101 (high word). The DATA_PTR for a read with DATA_LEN = 2 returns the raw low/high pair; the engineer must construct the REAL by reordering if the slave transmits in a different endianness.
  • Polling overlap: Calling the same instance DB with REQ re-triggered before BUSY = FALSE drops the new request silently. Sequence the REQ with the falling edge of DONE (or the rising edge of the error path) to ensure each transaction completes.
  • CM 1541 port configuration drift: The CM 1541 port must match the slave for baud (typically 9600 or 19200), parity (none, even, or odd), and stop bits. A mismatch produces 0x80D2 frame errors or no response. The Modbus library does not negotiate the link parameters; both ends must be configured identically.

Working ST Snippet for a Polling Loop

For projects where the same slave is polled for several disjoint address ranges, use a single instance DB and step the inputs through a small state machine. The snippet below shows a minimal reading loop for three holding-register blocks (PDU 100, 200, 250) from slave 0x65.

// State machine – call from OB1 every cycle
CASE iState OF
    0:  // Idle – issue request for PDU 100 (DATA_ADDR = 40101)
        "mdbMaster".REQ := FALSE;
        "mdbMaster".MB_ADDR := 16#65;       // 101 decimal
        "mdbMaster".MODE    := 0;            // FC 03, holding registers
        "mdbMaster".DATA_ADDR := 40101;      // PDU 100
        "mdbMaster".DATA_LEN  := 2;          // 2 words
        "mdbMaster".DATA_PTR  := "data".block1;
        "mdbMaster".REQ := TRUE;
        iState := 1;

    1:  // Wait for completion
        IF NOT "mdbMaster".BUSY THEN
            "mdbMaster".REQ := FALSE;
            IF "mdbMaster".ERROR THEN
                // Log STATUS, do not advance
                iErrorLast := "mdbMaster".STATUS;
            END_IF;
            // Next request – PDU 200 (DATA_ADDR = 40201)
            "mdbMaster".DATA_ADDR := 40201;
            "mdbMaster".DATA_LEN  := 4;
            "mdbMaster".DATA_PTR  := "data".block2;
            "mdbMaster".REQ := TRUE;
            iState := 2;
        END_IF;

    2:  // Wait for completion of block 2
        IF NOT "mdbMaster".BUSY THEN
            "mdbMaster".REQ := FALSE;
            IF "mdbMaster".ERROR THEN
                iErrorLast := "mdbMaster".STATUS;
            END_IF;
            // Next request – PDU 250 (DATA_ADDR = 40251)
            "mdbMaster".DATA_ADDR := 40251;
            "mdbMaster".DATA_LEN  := 1;
            "mdbMaster".DATA_PTR  := "data".block3;
            "mdbMaster".REQ := TRUE;
            iState := 3;
        END_IF;

    3:  // Wait for completion of block 3
        IF NOT "mdbMaster".BUSY THEN
            "mdbMaster".REQ := FALSE;
            IF "mdbMaster".ERROR THEN
                iErrorLast := "mdbMaster".STATUS;
            END_IF;
            iState := 0;       // Loop back to block 1
        END_IF;
END_CASE;

The total cycle time for the loop above is the sum of the three round-trip latencies. At 9600 baud with a 1 ms inter-frame gap, each transaction is dominated by the slave's response delay; budget roughly 50–100 ms per block for a typical sensor. Cycle times of 150–500 ms are common for small register maps.

Frequently Asked Questions

How do I read Modbus holding register at protocol address 100 on a Siemens S7-1500?

Set MODE = 0 (FC 03, Read Holding Registers), set DATA_ADDR = 100 + 40001 = 40101, and set DATA_LEN to the number of 16-bit words to fetch. The block subtracts 40001 internally and sends FC 03 with PDU address 0x0064 (100) on the serial line.

Why is my Modbus_Master returning STATUS 0x80C8 with a valid-looking address?

0x80C8 is "invalid parameter." The most common cause is DATA_ADDR outside the range allowed for the selected MODE—for example, 40101 with MODE = 4 (Input Registers), or 30001 with MODE = 0 (Holding Registers). Confirm that the leading digit of DATA_ADDR matches the MODE: 0xxxx for coils, 1xxxx for discrete inputs, 3xxxx for input registers, 4xxxx for holding registers.

What is the difference between MODE 0 and MODE 4?

MODE 0 issues FC 03 (Read Holding Registers) and expects a 4xxxx DATA_ADDR. MODE 4 issues FC 04 (Read Input Registers) and expects a 3xxxx DATA_ADDR. The function code and the address base both change, and many slaves do not implement FC 04; using the wrong MODE produces exception 01 from the slave or silent 0x80D4 errors on the master.

Can I read more than 125 holding registers in a single Modbus_Master call?

No. The Modbus specification limits FC 03 to 125 words per request, and the S7-1500 Modbus library enforces this limit (DATA_LEN ≤ 125 for MODE 0). For larger ranges, split the read into multiple transactions and stitch the result in the PLC. The same limit applies to FC 04. FC 16 (Write Multiple Registers) is limited to 123 words (246 bytes).

How do I address a holding register with a PDU address above 9998 on a Siemens S7-1500?

The standard Modbus library's MODE 0 only accepts DATA_ADDR from 40001 to 49999, which corresponds to PDU addresses 0–9998. To address PDU addresses 9999 and above, switch to the MODBUS_PN library (which carries the full 16-bit address space) or use Modbus TCP via MB_CLIENT, where the MBAP header carries the full 0–65535 PDU address without the 4xxxx offset.

Back to blog