Resolving S7-1200 MB_MASTER Error 8189: Modbus DATA_ADDR Format

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

Problem Overview

The Siemens S7-1200 MB_MASTER instruction (used with a CM 1241 communication module or the onboard RS485 port of the CPU in PTP mode) is the standard way to read and write Modbus RTU slaves. A common field failure is the following symptom set:

  • Slave documentation lists registers as 301000, 401000, 41000, or similar 5- or 6-digit numbers.
  • The programmer copies that value directly into the DATA_ADDR input of MB_MASTER.
  • The BUSY output toggles (true/false) and the DONE output never sets.
  • The STATUS output reports 16#8189 (decimal 8189).
  • After changing the address, the STATUS error disappears but no data is returned and BUSY still toggles indefinitely.

Status 16#8189 is a Modbus protocol error returned by the slave. The hex code breaks down as 0x80 (Modbus exception bit, set on the high bit) plus 0x09 (exception code 02 = Illegal Data Address). It is the slave telling the master that the requested offset is outside its defined register map. The MB_MASTER instruction is working correctly; the address is simply being passed in the wrong format.

Symptom key: STATUS = 16#8189 = slave rejected the start address. STATUS = 0 with BUSY toggling and no data update = the master timed out waiting for a response, or the read completed but the local pointer is misaligned. Both are almost always an address or mode mismatch on the S7-1200 side.

Modbus Address Convention Reference

Modbus uses two parallel address representations that confuse even experienced engineers because slave manuals and PLC tag structures use them interchangeably.

1. Modicon / Schneider 5- and 6-digit notation

This is the human-readable convention used in slave documentation. The leading digit is a function-class indicator and the trailing digits are a 1-based offset:

Modicon prefix Register class Function code(s) Offset range (1-based)
0xxxxx Coils (read/write bits) 01, 05, 15 000001 to 065536
1xxxxx Discrete Inputs (read-only bits) 02 100001 to 165536
3xxxxx Input Registers (read-only 16-bit) 04 300001 to 365536
4xxxxx Holding Registers (read/write 16-bit) 03, 06, 16 400001 to 465536

2. Modbus PDU (protocol data unit) address

The Modbus Application Protocol V1.1b3 specification defines the on-the-wire address as a 16-bit unsigned integer in the range 0x0000 to 0xFFFF (0 to 65535), and that range is 0-based for every register class. There is no class prefix on the wire. The class is selected by the function code sent in the same request, not by the address itself.

The S7-1200 MB_MASTER instruction speaks the PDU format, not the Modicon notation. DATA_ADDR expects the 0-based offset and MODE expects the function class.

Root Cause: Address Format Mismatch

When a slave manual prints 401000, it is saying "Holding Register, offset 1000 (1-based)". Three things can be wrong when this number is dropped directly into DATA_ADDR:

  1. Offset is 1-based in the manual, 0-based on the wire. The value 1000 in the manual equals PDU address 999.
  2. The class prefix (4) is not part of the address. DATA_ADDR = 401000 is the 16-bit value 401000, which is way above the 65535 limit and is rejected by the slave as an illegal data address (status 16#8189).
  3. Function class is controlled by MODE, not by the address. If the manual says 301000 but the user wants Holding Registers, the manual is mislabeled or the engineer is using the wrong function class. The class must be set in MODE, not inferred from the leading digit of DATA_ADDR.
Why the symptom changes when 41000 is used: 41000 is below the 65535 ceiling and does not violate the PDU range, so the slave does not return exception 02. However, address 41000 in PDU space is the 41001st register of whatever class MODE selects, which is not where the data actually lives. The master may then time out, return zeros, or read garbage that updates the wrong holding register in the local pointer DB. That is the second symptom in the field report (STATUS = 0, BUSY toggling, no useful data).

Correct DATA_ADDR and MODE Mapping

For each Modicon-style address in the slave manual, compute the PDU address and the MODE value as follows:

Conversion formulas

  • Holding Register 4xxxxx: DATA_ADDR = (xxxxx - 1), MODE = 3 (read), 6 (write single), or 8 (write multiple).
  • Input Register 3xxxxx: DATA_ADDR = (xxxxx - 1), MODE = 4 (read only).
  • Discrete Input 1xxxxx: DATA_ADDR = (xxxxx - 100001), MODE = 2 (read only).
  • Coil 0xxxxx: DATA_ADDR = (xxxxx - 1), MODE = 0 (read), 5 (write single), or 7 (write multiple).

Conversion table for common manual values

Manual address Register class DATA_ADDR (0-based) MODE (read) MODE (write)
400001 Holding Register 1 0 3 6 / 8
401000 Holding Register 1000 999 3 6 / 8
401001 Holding Register 1001 1000 3 6 / 8
41001 Holding Register 1001 (compact) 1000 3 6 / 8
300001 Input Register 1 0 4 n/a
301000 Input Register 1000 999 4 n/a
100001 Discrete Input 1 0 2 n/a
000001 Coil 1 0 0 5 / 7

Step-by-Step Resolution in TIA Portal

The procedure below is for an S7-1200 CPU 121x with a CM 1241 RS485 module (CB 1241 RS485 is also supported). The MB_MASTER block lives in the "Communication" folder of the Instructions task card under "Communication Processor" or in the legacy library under MODBUS.

Prerequisites

  • CPU 121x firmware V4.0 or later (V4.2 recommended for the CM 1241 V3 modules). Earlier firmwares have a smaller MB_MASTER mode subset.
  • CM 1241 (RS232, RS485, or RS422) inserted and configured in Device Configuration with a port that is set to "Modbus Master (RTU)" or to "Freeport/PTP" if the manual control variant is used.
  • An instance DB for MB_MASTER (created automatically when the block is inserted, or supplied manually).
  • Slave baud rate, parity, data bits, and stop bits known and matching the slave.

Step 1. Identify the slave register class

Open the slave manual and locate the register map. For each value you intend to read, note the prefix and the trailing offset. For example, if the manual lists "Register 401000 = Process Value" the register class is Holding Register and the 1-based offset is 1000.

Step 2. Convert to PDU address

Subtract 1 from the 1-based offset. The result is the integer that goes into DATA_ADDR. For register 401000, DATA_ADDR = 999. For register 401001, DATA_ADDR = 1000. If the manual is explicit that the offsets are 0-based, no subtraction is needed.

Step 3. Select the MODE value

Set MODE to the function code selector that matches the register class and the operation direction. Use the table above. For a read of a Holding Register, MODE = 3.

Step 4. Wire the instance DB and pointer

Pass a VARIANT pointer or a typed data block to the DATA_PTR input. The buffer length is set by DATA_LEN. The MB_MASTER instance DB stores the request internally; the data buffer is the structure the user supplies.

Step 5. Trigger the request

Set REQ = TRUE on a rising edge for each new transaction. REQ must be reset before the next call; a stuck REQ causes MB_MASTER to re-trigger and starve other slaves on a multi-drop segment.

Step 6. Evaluate the response

Poll DONE and ERROR. When DONE = TRUE and ERROR = FALSE, the read is complete and the buffer is valid. When ERROR = TRUE, read STATUS for the diagnostic code.

Example: SCL Call in an OB

The following SCL block reads 10 Holding Registers starting at slave offset 999 (manual register 401000) and writes the data to a global DB of WORDs.

// SCL - MB_MASTER example for S7-1200
// Reads 10 Holding Registers starting at PDU address 999
// (equivalent to Modicon registers 401000..401009)

#MB_MASTER_DB.REQ        := FALSE;          // one-shot
#MB_MASTER_DB.MB_ADDR    := 1;              // Modbus slave unit ID
#MB_MASTER_DB.MODE       := 3;              // 03 = Read Holding Registers
#MB_MASTER_DB.DATA_ADDR  := 999;            // 0-based start offset
#MB_MASTER_DB.DATA_LEN   := 10;             // 10 registers
#MB_MASTER_DB.DATA_PTR   := P#DB100.DBX0.0 BYTE 20; // 10 words = 20 bytes
#MB_MASTER_DB.BAUDRATE   := 9600;
#MB_MASTER_DB.PARITY     := 0;              // 0 = even
#MB_MASTER_DB.FLOW_CTRL  := 0;              // 0 = none
#MB_MASTER_DB.TIMEOUT    := 1000;           // 1000 ms

// Trigger on rising edge of request
IF #StartRead AND NOT #ReadBusy THEN
    #MB_MASTER_DB.REQ := TRUE;
END_IF;

IF #MB_MASTER_DB.DONE THEN
    #ReadBusy := FALSE;
    #ReadOK   := TRUE;
ELSIF #MB_MASTER_DB.ERROR THEN
    #ReadBusy := FALSE;
    #ReadError := TRUE;
    #LastStatus := #MB_MASTER_DB.STATUS;
ELSE
    #ReadBusy := #MB_MASTER_DB.BUSY;
END_IF;
DATA_PTR sizing: The pointer must reference at least DATA_LEN * 2 bytes for word-oriented modes (3, 4, 6, 8) and ceil(DATA_LEN / 8) bytes for bit-oriented modes (0, 1, 2, 5, 7, 15). A short pointer causes STATUS = 16#80C3 (area length error) at the S7-1200 side, not 16#8189 at the slave side.

Programmatic Address Conversion (SCL Function)

When a slave manual is loaded as engineering data and the 5- or 6-digit numbers must be mapped into MB_MASTER calls at runtime, use a small conversion function so the conversion is explicit and auditable.

// SCL FC "Conv_ManualAddr_To_DataAddr"
// Input : ManualAddr  INT   // 5- or 6-digit value from the slave manual
//         RegClass    BYTE  // 0=coil, 1=discrete in, 3=in reg, 4=hold reg
// Output: DataAddr    INT   // 0-based offset for MB_MASTER.DATA_ADDR
//         Mode        BYTE  // 0,2,3,4,5,6,7,8 selection for MB_MASTER.MODE
//         OK          BOOL  // FALSE if ManualAddr is out of range

CASE #RegClass OF
    0: // 0xxxxx Coils
        IF (#ManualAddr >= 1) AND (#ManualAddr <= 65536) THEN
            #DataAddr := WORD_TO_INT(#ManualAddr) - 1;
            #Mode     := 0;
            #OK       := TRUE;
        ELSE
            #OK := FALSE;
        END_IF;
    1: // 1xxxxx Discrete Inputs
        IF (#ManualAddr >= 100001) AND (#ManualAddr <= 165536) THEN
            #DataAddr := WORD_TO_INT(#ManualAddr) - 100001;
            #Mode     := 2;
            #OK       := TRUE;
        ELSE
            #OK := FALSE;
        END_IF;
    3: // 3xxxxx Input Registers
        IF (#ManualAddr >= 300001) AND (#ManualAddr <= 365536) THEN
            #DataAddr := WORD_TO_INT(#ManualAddr) - 300001;
            #Mode     := 4;
            #OK       := TRUE;
        ELSE
            #OK := FALSE;
        END_IF;
    4: // 4xxxxx Holding Registers
        IF (#ManualAddr >= 400001) AND (#ManualAddr <= 465536) THEN
            #DataAddr := WORD_TO_INT(#ManualAddr) - 400001;
            #Mode     := 3;
            #OK       := TRUE;
        ELSE
            #OK := FALSE;
        END_IF;
ELSE
    #OK := FALSE;
END_CASE;

Verification Procedure

  1. Compile and download the S7-1200 program. Go online in TIA Portal.
  2. Open the MB_MASTER instance DB in the watch table or a monitor view.
  3. Force REQ = TRUE for one cycle, then watch BUSY rise and STATUS remain 0.
  4. After the slave response, confirm DONE = TRUE and STATUS = 0. The status 16#8189 must not reappear.
  5. Inspect the data buffer pointed to by DATA_PTR. Compare the first word to the value reported by the slave's configuration tool (or to a value that the slave is known to publish, e.g. a process value with a known range).
  6. Capture a Modbus trace with a protocol analyzer (such as a TIA-side trace, a TAP on the RS485 lines, or a software sniffer like the Modbus Doctor or a Wireshark capture with the pcap-modbus dissector) and confirm the request frame contains the expected function code (03 for Holding Registers, 04 for Input Registers) and the 0-based offset you intended to send.
Trace tell: If the request on the wire shows the function code you selected and the offset 999 (decimal) for a manual register 401000, the configuration is correct and the slave is responding. If the wire shows function code 03 with offset 0x9C40 (40000) or some other unexpected value, the conversion in TIA Portal is wrong.

STATUS Code Reference for MB_MASTER (S7-1200)

STATUS (hex) STATUS (dec) Source Meaning
16#0000 0 Master No error / transaction complete
16#7000 28672 Master No request active, REQ = FALSE
16#7001 28673 Master Request is being processed, BUSY = TRUE
16#7002 28674 Master Request queued (multi-slave arbitration)
16#80C3 32963 Master Data pointer / area length error (S7-1200-side)
16#8188 33160 Slave Modbus exception 01 = Illegal Function
16#8189 33161 Slave Modbus exception 02 = Illegal Data Address
16#818A 33162 Slave Modbus exception 03 = Illegal Data Value
16#818B 33163 Slave Modbus exception 04 = Slave Device Failure
16#818C 33164 Slave Modbus exception 05 = Acknowledge (long operation)
16#818D 33165 Slave Modbus exception 06 = Slave Device Busy
16#818E 33166 Slave Modbus exception 07 = NAK / Parity / Memory Error
16#818F 33167 Slave Modbus exception 08 = Memory Parity Error

The 0x80 high byte marks a slave-returned exception (Modbus exception bit OR'd with the exception code). A code below 16#8000 is generated by the S7-1200 itself; a code at or above 16#8000 originates at the slave.

Troubleshooting Matrix

Observed symptom Most likely cause Fix
STATUS = 16#8189, no data update Modicon-style address (e.g. 401000) passed directly to DATA_ADDR and exceeds 65535, or the offset is wrong class for MODE Strip the class prefix, subtract 1, and set MODE to the function code selector for the desired class
STATUS = 0, BUSY toggles, no data Address within PDU range but pointing to an unrelated register; slave returns valid but wrong data and master times out before any update Re-check the manual and recompute the 0-based offset; capture a Modbus trace to confirm the offset sent on the wire
STATUS = 16#8188 Function code in MODE not supported by the slave (e.g. trying to read Input Registers on a slave that exposes only Holding Registers) Use the supported function code; refer to the slave manual for the supported register class
STATUS = 16#80C3 Pointer area too small or misaligned for DATA_LEN Resize the destination DB / data block to at least DATA_LEN * 2 bytes (or ceil(DATA_LEN/8) for bit modes)
Reads return zero even though DONE = TRUE Byte-swap or word-swap issue between S7-1200 big-endian and slave little-endian register layout Apply byte-swap on the S7-1200 side using SWAP or the standard swap FB; confirm with a known value from the slave
Works for slave 1, fails for slave 2 on the same multi-drop bus Address collision; both slaves use the same Modbus unit ID Re-assign MB_ADDR on at least one device; verify with a poll that only one slave replies per request

Field-Proven Caveats

  • 1-based vs 0-based manuals. Some vendors (notably older ABB and Schneider controllers) document Modicon-style numbers and tell the engineer the offset is 1-based. Others (notably certain Chinese instrument manufacturers) document PDU offsets and lead the engineer to add 1 unnecessarily. The Modbus Application Protocol V1.1b3 specifies 0-based PDU addresses. Trust the PDU, not the manual format.
  • Register 401000 vs 41000. Both notations refer to the same Holding Register (PDU offset 999) and differ only in writing style. The earlier helper in the field report is correct that 41000 and 401000 refer to the same register, but neither should be passed literally to DATA_ADDR; the correct value is 999.
  • Function class ambiguity. The trailing "3" in the user's original 301000 notation can be misread as a function code (03 = Read Holding Registers). The other helper in the field report flags this possibility. The correct interpretation depends on the manual: if the manual calls the register an Input Register, MODE = 4; if it is a Holding Register, MODE = 3. The leading digit of the address is a class hint, not a function code on the wire.
  • Word vs byte ordering. The S7-1200 stores WORDs in big-endian. Modbus RTU is big-endian on the wire. A few industrial sensors (some Danfoss and Carel devices) ship firmware that puts the high byte second, which is unusual and can be misread as a swap problem. Confirm with a known value before assuming an address problem.
  • CM 1241 firmware. On a CM 1241 (RS232/RS485) module, the baud/parity/flow settings on the MB_MASTER call must match the port configuration in Device Configuration. Mismatches surface as timeouts, not as 16#8189. If you see timeouts, fix the port settings first and then revisit the address.
  • Multi-drop unit ID. The Modbus unit ID (MB_ADDR) is not the same as the PDU address. MB_ADDR identifies the slave on the bus; DATA_ADDR identifies the register inside the slave. Conflating them is a common cause of the original symptom.

Related Diagnostics: When STATUS Is Not 16#8189

If the converted address is correct and the slave stops returning 16#8189 but the data buffer remains at its initial value, move on to the following checks before assuming another address problem:

  1. Inspect the CM 1241 port LEDs (Tx/Rx). One direction only (Tx only, no Rx) indicates a wiring, termination, or echo problem, not an address problem.
  2. Verify the Modbus RTU inter-frame silence is at least 3.5 character times. A polled S7-1200 master uses the configured baud rate to schedule this; a manually written PTP master must insert a delay in the program.
  3. Confirm the slave supports the requested function code with a single register poll at a register the manual guarantees (e.g. 400001 = product code). If that succeeds, the bus is healthy and the address map is the issue.
  4. Check the Modbus RTU CRC. The CM 1241 calculates this automatically. If a manual Modbus implementation is wrapped around the S7-1200, the CRC may be wrong and the slave will not respond at all, which looks identical to a wrong address from the master side.

Documentation References

Why does MB_MASTER return STATUS 16#8189 when I put 401000 in DATA_ADDR?

Because the value 401000 is the Modicon-style notation "Holding Register, offset 1000 (1-based)" and exceeds the 16-bit PDU address range (0 to 65535). The slave rejects the offset as Illegal Data Address (Modbus exception 02). Strip the leading class digit and subtract 1: set DATA_ADDR = 999 and MODE = 3 (Read Holding Registers).

Should I use 41000 or 401000 for a register the manual lists as "401000"?

Neither. Both 41000 and 401000 are textual notations for the same register (Holding Register at 1-based offset 1000). On the wire the value is 0-based and the class is selected by MODE. The correct DATA_ADDR is 999 and the correct MODE is 3 (Read Holding Registers) for a read, 6 (Write Single) for a single-register write, or 8 (Write Multiple) for a multi-register write.

My slave manual says the registers are at 301000, but I want to read them as Holding Registers. How do I handle that?

Confirm with the vendor whether the register is actually an Input Register (function 04) or a Holding Register (function 03). The 3xxxxx prefix in the manual is a strong hint that it is an Input Register, in which case you must use MODE = 4 to read it. If the vendor confirms it is a Holding Register, the manual notation is wrong and you should treat it as a 4xxxxx register: DATA_ADDR = 999, MODE = 3.

STATUS is 0 and BUSY toggles but no data is returned. What is wrong?

Either the address is within the legal range but pointing to an empty or wrong register in the slave, or the CM 1241 timed out waiting for a response. Capture a Modbus trace on the RS485 lines and confirm the offset sent on the wire matches the register you want. If the trace shows the correct request and no response, fix wiring, termination, and baud/parity. If the trace shows the correct request and a response, check the DATA_PTR alignment and any byte-swap logic.

Can I pass the 5/6-digit Modicon address directly to DATA_ADDR in S7-1200 MB_MASTER?

No. The MB_MASTER instruction on the S7-1200 expects a 0-based 16-bit offset in DATA_ADDR and the register class in MODE. Passing a 5- or 6-digit value directly either violates the address range (causing STATUS 16#8189 from the slave) or silently reads from the wrong register. Always convert the Modicon address to its 0-based offset and set MODE explicitly.

Back to blog