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_ADDRinput ofMB_MASTER. - The
BUSYoutput toggles (true/false) and theDONEoutput never sets. - The
STATUSoutput reports16#8189(decimal 8189). - After changing the address, the
STATUSerror disappears but no data is returned andBUSYstill 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.
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:
-
Offset is 1-based in the manual, 0-based on the wire. The value
1000in the manual equals PDU address999. -
The class prefix (4) is not part of the address.
DATA_ADDR = 401000is the 16-bit value401000, which is way above the 65535 limit and is rejected by the slave as an illegal data address (status16#8189). -
Function class is controlled by MODE, not by the address. If the manual says
301000but the user wants Holding Registers, the manual is mislabeled or the engineer is using the wrong function class. The class must be set inMODE, not inferred from the leading digit ofDATA_ADDR.
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), or8(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), or7(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_MASTERmode 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_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
- Compile and download the S7-1200 program. Go online in TIA Portal.
- Open the
MB_MASTERinstance DB in the watch table or a monitor view. - Force
REQ = TRUEfor one cycle, then watchBUSYrise andSTATUSremain0. - After the slave response, confirm
DONE = TRUEandSTATUS = 0. The status16#8189must not reappear. - 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). - 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.
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
41000and401000refer to the same register, but neither should be passed literally toDATA_ADDR; the correct value is999. -
Function class ambiguity. The trailing "3" in the user's original
301000notation 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_MASTERcall must match the port configuration in Device Configuration. Mismatches surface as timeouts, not as16#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_ADDRidentifies the slave on the bus;DATA_ADDRidentifies 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:
- 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.
- 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.
- 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. - 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
- DATA_ADDR and MODE parameters (S7-1200 MB_MASTER) - TIA Portal V21 documentation
- Modbus Application Protocol V1.1b3 - Modbus Organization
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.