S7-1200 Modbus RTU Master: Sequencing 5 Slaves with MB_MASTER
Overview
A SIMATIC S7-1200 CPU1214C acting as a Modbus RTU master can poll up to 247 slave addresses on a single RS485 segment, but the on-board firmware MB_MASTER instruction handles only one outstanding request at a time per PtP (point-to-point) port. To exchange data with five slaves (three read-only, one write-only, one read/write) you must implement a sequencer that arbitrates the shared port, fires each transaction when its turn comes up, and processes the DONE/ERROR outputs of every MB_MASTER instance.
This reference walks through the hardware, the TIA Portal configuration of the MB_COMM_LOAD and MB_MASTER instructions, the sequencer state machine, sample SCL code, diagnostics, and a troubleshooting matrix for the most common fault codes (STATUS = 0x0001 through 0x80C8).
Prerequisites
- S7-1200 CPU1214C with firmware V4.0 or higher (CPU 1214C DC/DC/DC or DC/DC/Rly; order number 6ES7214-1AG40-0XB0 or later).
- Communications module CM 1241 RS485 (6ES7241-1CH30-1XB0) or CB 1241 RS485 (6ES7241-1CH31-0XB0) plugged into the left bus of the CPU.
- TIA Portal V15.1 or later with the SIMATIC S7-1200 Communication Processor and Modbus RTU documentation installed.
- Five Modbus RTU slaves each with a unique address in the range 1-247. Confirm each device's register map (coil, holding, input register).
- Two-wire RS485 daisy-chain cable, 120 Ω termination resistors at both physical ends, and a common ground reference.
Hardware and Network Topology
Wire the CM 1241 RS485 to the bus as follows:
| CM 1241 pin | Signal | RS485 conductor |
|---|---|---|
| 3 | TxD+/RxD+ (non-inverting) | Conductor A (Data+) |
| 8 | TxD-/RxD- (inverting) | Conductor B (Data-) |
| 5 | Functional Earth / shield | Shield, one end only |
The CM 1241 provides internal 10 kΩ fail-safe bias resistors that hold the line idle at logical 1 (Mark). External 120 Ω termination is mandatory at the two farthest physical nodes only; adding extra terminators attenuates the signal and causes intermittent framing errors (status 0x80C4).
Set the RS485 bias/termination DIP switches on the module itself (CM 1241 has SW1–SW3; CB 1241 has none, termination is software-selected). On the CM 1241, SW1 = termination, SW2 = pull-up, SW3 = pull-down.
TIA Portal Project Configuration
Adding the Modbus RTU Instructions
No extra library is required for firmware V4.0 and later. The instructions ship with the global instruction set:
- In the project tree, expand PLC_1 → Program blocks → System blocks.
- Insert MB_COMM_LOAD (DB-type, instance DB auto-generated). It configures the port once at startup.
- Insert one MB_MASTER instance per slave (5 instances minimum). Each instance owns its own instance DB holding the request and status data.
MB_COMM_LOAD Parameter Mapping
| Input | Data type | Value (typical) | Meaning |
|---|---|---|---|
| REQ | BOOL | TRUE (pulse) | Trigger port reconfiguration |
| PORT | HW_IO | CM/CB slot | Identifier of the PtP port |
| BAUD | DINT | 9600 / 19200 | Baud rate (110 to 115 200) |
| PARITY | UINT | 2 (even) | 0=none, 1=odd, 2=even |
| FLOW_CTRL | UINT | 0 | 0=none for RS485 half-duplex |
| RTS_ON_DLY | UINT | 0 | RTS-ON delay (ms) |
| RTS_OFF_DLY | UINT | 0 | RTS-OFF delay (ms) |
| RESP_TO | UINT | 1000 | Response timeout (ms), 5-65535 |
| DONE | BOOL | – | Configuration complete (one-shot) |
| ERROR | BOOL | – | Configuration error |
| STATUS | WORD | – | Error code when ERROR=TRUE |
RESP_TO must exceed the worst-case slave turnaround. Most RTU slaves answer within 50 ms; set 1,000 ms for safety. A timeout smaller than the slave's processing time produces status 0x80C6 (response timeout).MB_MASTER Instruction Deep Dive
The MB_MASTER instruction handles the Modbus ADU (Application Data Unit), assembles the CRC-16, and posts one transaction per rising edge of REQ. Per the SIMATIC S7-1200 Communication manual, the supported MODE values map to standard Modbus function codes:
| MODE | FC | Direction | Data type | Data_ADDR unit |
|---|---|---|---|---|
| 0 | 03 | Read Holding Registers | Word array | Register number (40001 base) |
| 1 | 01 | Read Coils | Bool array | Coil number (00001 base) |
| 2 | 02 | Read Discrete Inputs | Bool array | Input number (10001 base) |
| 4 | 04 | Read Input Registers | Word array | Input register (30001 base) |
| 5 | 05 | Write Single Coil | Bool array[1] | Coil number (00001 base) |
| 6 | 06 | Write Single Register | Word array[1] | Register number (40001 base) |
| 100 | 15 | Write Multiple Coils | Bool array | Coil number (00001 base) |
| 101 | 16 | Write Multiple Registers | Word array | Register number (40001 base) |
The DATA_ADDR parameter uses the zero-based Modbus address. To read holding register 40001, set DATA_ADDR = 0. To read 40010, set DATA_ADDR = 9. Maximum DATA_LEN is 125 words (FC 03/04/16) or 2,048 bits (FC 01/02/15). See the TIA Portal S7-1200 Modbus RTU instruction reference for full specifications.
Sequencer State Machine for 5 Slaves
Because the port is half-duplex and the firmware does not queue, you need a deterministic round-robin sequencer. The pattern is:
- Cycle through five steps (one per slave).
- On entry to step N, set
REQ = TRUEon the corresponding MB_MASTER. - Wait until
DONE = TRUEorERROR = TRUE. - Reset
REQ, copy data on success, log error on failure. - Advance to step N+1 mod 5.
Use a small cyclic OB (OB1 or OB35) plus an instance FB that owns the state. The minimum inter-frame gap is 3.5 character times per Modbus RTU specification; the firmware inserts this automatically when the next REQ is fired, so no manual delay is needed as long as you release the bus within RESP_TO.
Sample SCL Implementation
The following code creates one instance DB per slave and a single sequencer. Declare in a static area of FB_ModbusMasterPoll:
FUNCTION_BLOCK FB_ModbusMasterPoll
VAR
mbCommLoad : MB_COMM_LOAD; // port configuration
mbMaster_1 : MB_MASTER; // slave 1 - read holding regs (10 words)
mbMaster_2 : MB_MASTER; // slave 2 - read input regs (8 words)
mbMaster_3 : MB_MASTER; // slave 3 - read coils (16 bits)
mbMaster_4 : MB_MASTER; // slave 4 - write multiple regs (5 words)
mbMaster_5 : MB_MASTER; // slave 5 - read 4 / write 2 words
step : INT := 0;
cycleCount : DINT;
errorCount_1..5 : DINT;
// data buffers - sized for the largest expected payload
dataSlave1 : ARRAY[0..9] OF WORD; // 10 holding regs from device #1
dataSlave2 : ARRAY[0..7] OF WORD; // 8 input regs from device #2
dataSlave3 : ARRAY[0..15] OF BOOL; // 16 coils from device #3
dataSlave4 : ARRAY[0..4] OF WORD; // 5 holding regs to device #4
dataSlave5In : ARRAY[0..3] OF WORD; // 4 holding regs from device #5
dataSlave5Out : ARRAY[0..1] OF WORD; // 2 holding regs to device #5
END_VAR
BEGIN
// -- 1) Configure port on first cycle --
mbCommLoad(REQ := TRUE, PORT := "Cm1241_RS485",
BAUD := 9600, PARITY := 2, FLOW_CTRL := 0,
RESP_TO := 1000);
IF NOT mbCommLoad.DONE THEN RETURN; END_IF;
// -- 2) Sequencer: one transaction per OB1 pass --
CASE step OF
0: // Slave 1, read 10 holding registers (FC 03) starting at 40001
mbMaster_1(REQ := TRUE, MB_ADDR := 1, MODE := 0,
DATA_ADDR := 0, DATA_LEN := 10,
DATA_PTR := dataSlave1);
IF mbMaster_1.DONE THEN
errorCount_1 := 0;
step := 1;
ELSIF mbMaster_1.ERROR THEN
errorCount_1 := errorCount_1 + 1;
step := 1; // advance even on error to keep polling
END_IF;
1: // Slave 2, read 8 input registers (FC 04) starting at 30001
mbMaster_2(REQ := TRUE, MB_ADDR := 2, MODE := 4,
DATA_ADDR := 0, DATA_LEN := 8,
DATA_PTR := dataSlave2);
IF mbMaster_2.DONE OR mbMaster_2.ERROR THEN step := 2; END_IF;
2: // Slave 3, read 16 coils (FC 01) starting at 00017
mbMaster_3(REQ := TRUE, MB_ADDR := 3, MODE := 1,
DATA_ADDR := 16, DATA_LEN := 16,
DATA_PTR := dataSlave3);
IF mbMaster_3.DONE OR mbMaster_3.ERROR THEN step := 3; END_IF;
3: // Slave 4, write 5 holding registers (FC 16) starting at 40010
mbMaster_4(REQ := TRUE, MB_ADDR := 4, MODE := 101,
DATA_ADDR := 9, DATA_LEN := 5,
DATA_PTR := dataSlave4);
IF mbMaster_4.DONE OR mbMaster_4.ERROR THEN step := 4; END_IF;
4: // Slave 5, read 4 holding registers (FC 03) starting at 40001
mbMaster_5(REQ := TRUE, MB_ADDR := 5, MODE := 0,
DATA_ADDR := 0, DATA_LEN := 4,
DATA_PTR := dataSlave5In);
IF mbMaster_5.DONE OR mbMaster_5.ERROR THEN step := 5; END_IF;
5: // Slave 5, write 2 holding registers (FC 16) starting at 40006
// Re-trigger the same MB_MASTER instance with a different MODE/DATA_LEN.
mbMaster_5(REQ := TRUE, MB_ADDR := 5, MODE := 101,
DATA_ADDR := 5, DATA_LEN := 2,
DATA_PTR := dataSlave5Out);
IF mbMaster_5.DONE OR mbMaster_5.ERROR THEN
cycleCount := cycleCount + 1;
step := 0;
END_IF;
END_CASE;
// -- 3) Edge-detect REQ so each step fires once --
mbMaster_1.REQ := FALSE; mbMaster_1.REQ := (step = 0) AND NOT mbMaster_1.DONE;
mbMaster_2.REQ := FALSE; mbMaster_2.REQ := (step = 1) AND NOT mbMaster_2.DONE;
mbMaster_3.REQ := FALSE; mbMaster_3.REQ := (step = 2) AND NOT mbMaster_3.DONE;
mbMaster_4.REQ := FALSE; mbMaster_4.REQ := (step = 3) AND NOT mbMaster_4.DONE;
mbMaster_5.REQ := FALSE; mbMaster_5.REQ := (step = 4 OR step = 5) AND NOT mbMaster_5.DONE;
END_FUNCTION_BLOCK
mbMaster_5 instance because the same slave has both a read and a write transaction. Each instance of MB_MASTER can service any number of sequential transactions; the only requirement is that REQ is pulsed only after the previous DONE/ERROR has cleared.Mapping 5 Slave Profiles to MB_MASTER
| Slave | Address | Function | FC | MB_MASTER MODE | DATA_ADDR (zero-based) | DATA_LEN | Buffer |
|---|---|---|---|---|---|---|---|
| #1 Read Holding Regs | 1 | Read | 03 | 0 | 0 | 10 words | dataSlave1[0..9] |
| #2 Read Input Regs | 2 | Read | 04 | 4 | 0 | 8 words | dataSlave2[0..7] |
| #3 Read Coils | 3 | Read | 01 | 1 | 16 | 16 bits | dataSlave3[0..15] |
| #4 Write Holding Regs | 4 | Write | 16 | 101 | 9 | 5 words | dataSlave4[0..4] |
| #5 Read+Write | 5 | Read | 03 | 0 | 0 | 4 words | dataSlave5In[0..3] |
| #5 Read+Write | 5 | Write | 16 | 101 | 5 | 2 words | dataSlave5Out[0..1] |
The total wall-clock scan time for one full round is approximately 6 × (Tframe + Tslave + Tgap). At 9,600 bit/s and a 32-byte payload, Tframe ≈ 35 ms; budget 50 ms per slave response → 300 ms round. To halve that, increase the baud rate to 38,400 bit/s and confirm each slave supports it.
Master vs Slave Instructions: When to Use MB_SLAVE
If the S7-1200 itself needs to be polled by a higher-level SCADA or by another PLC, deploy the MB_SLAVE instruction on a second PtP port (a CB 1241 can be added to the left bus). MB_SLAVE supports function codes 1, 2, 4, 5, and 15 for direct bit/word access into the process image. Refer to the MB_SLAVE instruction documentation for the full I/O map.
In the configuration discussed here, the S7-1200 is the master. MB_SLAVE is mentioned only to clarify the asymmetric role; it must not be called simultaneously with MB_MASTER on the same port.
Diagnostics and STATUS Code Matrix
| STATUS hex | Meaning | Root cause | Fix |
|---|---|---|---|
| 0x0000 | Idle | No active transaction | Normal |
| 0x0001 | Success, in progress | REQ accepted | Normal |
| 0x80C8 | Invalid MB_ADDR / MODE | Wrong parameter or unsup. FC | Validate slave # 1-247, MODE = 0/1/2/4/5/6/100/101 |
| 0x80D1 | REQ issued before previous DONE | Sequencer race | Add edge-detection on REQ |
| 0x80D2 | DATA_LEN out of range | LEN > 125 or < 1 | Re-size buffer; for FC 16 max 123 wrds |
| 0x80D4 | DATA_PTR not WORD/BOOL array | Wrong type at instance DB | Match MODE → BOOL for coils, WORD for registers |
| 0x80E1 | CRC error from slave | Electrical noise / baud mismatch | Check wiring, ground, parity, baud |
| 0x80E2 | Slave address mismatch | Wrong MB_ADDR or duplicate address on bus | Verify each slave's address switch |
| 0x80E3 | Function code not supported | Slave does not implement this FC | Check slave datasheet |
| 0x80E4 | Quantity out of slave range | DATA_ADDR + DATA_LEN exceeds map | Reduce DATA_LEN or shift address |
| 0x80E5 | Slave rejected write | Read-only register | Verify writeable memory map |
| 0x80C4 | Framing/parity error | Line noise, wrong parity, baud | Inspect wiring; check parity (most slaves use Even) |
| 0x80C6 | Response timeout | RESP_TO too low or slave silent | Increase RESP_TO; verify slave is powered |
"InstModbusMaster".STATUS. Create a watch table in TIA Portal with all five instances plus the sequencer step and cycleCount to monitor live polling health without pausing the CPU.Verification and Commissioning Procedure
- Compile and download the program. Switch the CPU to RUN; MB_COMM_LOAD should pulse DONE within 200 ms.
- Open Online & Diagnostics → Modbus trace (TIA V16+) or use the watch table to verify
stepcycles 0 → 5 → 0 in less than 500 ms for a full round. - Disconnect one slave physically. The corresponding MB_MASTER.ERROR should rise with STATUS
0x80C6; the sequencer must continue to the next step. - Reconnect and confirm STATUS returns to 0 and DONE pulses true.
- Trigger a Modbus scan from a third-party tool (e.g., Modbus Poll) using the same baud/parity and verify the S7-1200's view matches the slave's real registers.
- For write slaves, change
dataSlave4[0]online; confirm the slave reflects the new value within one cycle. - Record a 60-second Modbus trace. Expect exactly six transactions per cycle; any extra frames indicate bus collisions (typically a termination or duplicate address issue).
Troubleshooting Matrix
| Symptom | Likely cause | Diagnostic step | Remediation |
|---|---|---|---|
| All slaves return 0x80C6 timeout | No TX from CPU | Check "MB_COMM_LOAD".DONE | Verify PORT HW identifier; re-run MB_COMM_LOAD |
| One slave returns 0x80E2 | Duplicate or wrong address | Scan bus with master tool | Re-address slave with DIP or software |
| Random 0x80E1 CRC errors | Missing termination | Inspect both ends of RS485 | Install 120 Ω at the two farthest nodes only |
| Sequencer stuck on one step | REQ held high continuously | Watch MB_MASTER.REQ | Edge-detect REQ with previous-step DONE |
| Write transactions report 0x80E5 | Read-only register addressed | Compare DATA_ADDR with map | Use only FC 03 to read-only zones |
| Slaves 1-2 OK, slave 3 fails | Coil-buffer type mismatch | Check DATA_PTR declaration | Declare as ARRAY OF BOOL for MODE 1/2/5/100 |
| High MB_MASTER cycle time | Multiple writes per cycle | Profile OB1 execution | Move sequencer to OB35 (100 ms) for periodic polling |
Performance and Tuning Notes
- For polling rates above 50 Hz aggregate, move the sequencer from OB1 to OB35 (cyclic interrupt, 100 ms) so the CPU's main scan stays responsive to HMI and safety logic.
- If slaves support broadcast (address 0) and identical read maps, MB_MASTER can broadcast one FC 03 request; however most RTU slaves ignore writes via broadcast by design.
- The internal instance DBs (
InstModbusMaster_1etc.) retain their STATUS across STOP→RUN transitions; clear them withRESET_BITSduring startup if you need a clean slate. - For deterministic timing, set
RESP_TOto3.5 × (1 / baud) × 40ms plus the slave's worst-case latency.
Alternative Approaches
Beyond the manual sequencer, two production-ready patterns exist:
-
Siemens Support library (legacy): The S7-1200/S7-1500 Modbus RTU Master sample project on the Siemens Industry Online Support portal (entry ID 109742061) provides a ready-made FB
MB_RTU_MASTERwith cycle dispatch and 16-slot table. Use it for rapid deployment without hand-coding the sequencer. - Third-party libraries (e.g., rexhip): An open-source Modbus RTU master library for S7-1200 is available, providing high-level blocks for read/write with built-in reconnection. Such libraries are suitable for non-safety applications; validate CRC handling and STATUS mapping before deployment.
For most small-scale installations (≤ 8 slaves, < 100 ms scan) the sequencer pattern in this document outperforms a generic library because you retain direct visibility of every STATUS word and can scale the cycle to your application's precision needs.
FAQ
How many MB_MASTER instances do I need for 5 slaves with different read and write tag counts?
One instance per transaction direction per slave address. Five slaves with mixed read/write can be served by 6 instances if one slave needs both directions (e.g., 4 read-only slaves = 4 instances plus 1 slave with read+write = 2 instances, total 6). Each instance must be triggered one at a time via the sequencer.
What STATUS code indicates the slave is offline or unpowered?
STATUS 0x80C6 (response timeout). Increase RESP_TO in MB_COMM_LOAD to at least 1,000 ms, then verify the slave's power supply and RS485 wiring. No response within the timeout window always raises this code regardless of the underlying electrical issue.
Can MB_MASTER and MB_SLAVE run on the same S7-1200 simultaneously?
No. They share the same port resource and the firmware cannot arbitrate master vs slave on one half-duplex RS485 channel. Add a second CM/CB 1241 module if the CPU must act as both master and slave in the same project. See the MB_SLAVE documentation for port-binding rules.
Why does my read-only slave return 0x80E5 even though I only read?
STATUS 0x80E5 is returned for slave-side exceptions other than illegal function or address; it usually means the slave does not support the requested function code or the requested quantity. Verify the FC mapping in the slave's documentation and reduce DATA_LEN so it does not cross into unmapped register space.
What is the maximum total number of registers I can poll across 5 slaves?
There is no firmware-imposed aggregate limit, only the per-transaction ceiling of 125 words (or 2,048 bits for coils) and the port's response timeout. A typical 5-slave configuration with 32 registers each fits well within 300 ms at 19,200 bit/s. If you exceed that, lower the polling priority of non-critical slaves by skipping them every N cycles in the sequencer.