Overview
The Siemens Modbus RTU library for the S7-300/ET 200SP family separates the port configuration (FB MODBUS_COMM_LOAD) from the master polling logic (FB MODBUS_MASTER). This split is intentional: configuration parameters are static and applied once, while polling transactions are dynamic and executed every cycle. The most common commissioning failure mode is calling MODBUS_COMM_LOAD repeatedly in OB1, which reconfigures the port on every scan, breaks the running MODBUS_MASTER transaction, and produces intermittent timeouts. This article documents the correct initialization timing for a CPU 315 controlling a CM PtP module in an ET 200SP station, including the role of COM_RST and REQ.
CM PtP (6ES7137-6AA00-0BA0 or compatible) on PROFINET. The same logic applies to S7-300 CPUs with a CP 341 or CM PtP in the central rack; substitute the slot/HW identifier for the PORT input.Prerequisites
- STEP 7 (TIA Portal) V15.1 or higher, or STEP 7 V5.5 SPx with the "Modbus" library installed.
- Modbus RTU master library installed; for S7-1200/1500/ET 200SP this is delivered as part of the standard Modbus instruction set. For S7-300 classic library, the FBs ship with the Modbus driver DVD.
- ET 200SP station configured in HW Config / device view with the CM PtP module in the slot used for serial communication.
- Logical HW identifier of the CM PtP module noted from the device properties (e.g.
269for slot 1 in a typical ET 200SP head). - RS-485 termination enabled at both line ends (typically 120 Ω) when wiring multi-drop slaves.
Function Block Architecture
The library implements Modbus RTU as two cooperating FBs plus the underlying PtP driver:
| FB / Block | Role | Call Frequency |
|---|---|---|
MODBUS_COMM_LOAD |
Configures the CM PtP port (baud, parity, flow control, RTS delay) and primes the internal instance DB for the Modbus state machine. | One time, on warm/cold restart or port parameter change. |
MODBUS_MASTER |
Builds the Modbus request frame, sends it, and places the response in a data buffer. | Cyclically, every OB1 scan, or event-driven via REQ. |
| PtP driver / instance | Low-level send/receive, character timers, RS-485 direction control. | System tasks. |
Per the official Siemens Modbus documentation, Modbus_Comm_Load is configured to "configure a communications module for communication by means of the Modbus RTU protocol" and must be executed once before the master block can issue transactions (TIA Portal: Modbus_Comm_Load – Configure communication module).
MODBUS_COMM_LOAD Parameters
| Input | Type | Meaning | Typical Value (ET 200SP CM PtP) |
|---|---|---|---|
REQ |
BOOL | Rising edge triggers (re)configuration of the port. | One-shot pulse from startup logic. |
PORT |
UINT | HW identifier of the CM PtP from device configuration. | e.g. 269
|
BAUD |
DINT | Baud rate in bits/s. |
9600, 19200, 38400, 115200
|
PARITY |
UINT | Parity: 0=None, 1=Odd, 2=Even. |
2 (Even) for most Modbus RTU slaves. |
FLOW_CTRL |
UINT | 0=None (RS-485), 1=Hardware (RTS/CTS, RS-232). |
0 for 2-wire RS-485. |
RTS_ON_DLY / RTS_OFF_DLY
|
UINT | Direction-switch delays in ms for RS-485 transceiver. |
0 / 0 or small value (e.g. 10). |
RESP_TO |
UINT | Slave response timeout in ms. 0 uses default (1000 ms). |
1000 to 3000 depending on line. |
MODE |
USINT | Protocol selection. 4 = Modbus RTU master. |
4 |
COM_RST |
BOOL | Reset the instance DB and drop any pending Modbus state. | Pulse TRUE on startup or after fatal error. |
DONE |
BOOL | Configuration completed successfully (one cycle). | Set MB_ConfigDone flag. |
ERROR |
BOOL | Configuration failed. | Inspect STATUS. |
STATUS |
WORD | Detailed error code. | See STATUS table below. |
Per the Siemens support note for Modbus_Comm_Load: "Call Modbus_Comm_Load from a startup OB and execute it one time or use the first scan system flag to initiate the call to execute it one time" (Siemens Support: Modbus_Comm_Load initialization). Executing it more than once is supported only when port parameters genuinely change.
MODBUS_MASTER Parameters
| Input | Type | Meaning |
|---|---|---|
REQ |
BOOL | Rising edge starts a new transaction. In continuous mode leave TRUE once BUSY=FALSE. |
SLAVE |
USINT | Modbus slave address 1…247. |
MODE |
USINT | Function code: 1=Read Coils, 2=Read Discrete, 3=Read Holding, 4=Read Input, 5=Write Single Coil, 6=Write Single Register, 15=Write Multiple Coils, 16=Write Multiple Registers. |
DATA_ADDR |
UINT | Modbus register/coil address (0-based; library adds +1 for the wire protocol). |
DATA_LEN |
UINT | Number of elements (bits for FC 1/2/5/15, words for FC 3/4/6/16). |
DATA_PTR |
VARIANT | Pointer to the data buffer (DB or M area). For bit-level FCs, use a buffer of DATA_LEN/8 bytes rounded up. |
WRITE_READ |
BOOL | Direction: 0=read, 1=write (only relevant for FC 23 in some libraries). |
COM_RST |
BOOL | Reset the master instance DB and abort any in-flight transaction. |
Outputs: DONE pulses for one cycle on success, BUSY=TRUE while the request is outstanding, ERROR=TRUE with non-zero STATUS on failure.
Why the Split Between Configuration and Polling Exists
Modbus RTU is a single-master, multi-drop protocol with strict timing requirements: a 3.5-character silent interval marks the start and end of every frame. If the port is reconfigured between frames, the character timer is restarted, the transmitter direction toggles, and an in-flight frame is corrupted. Therefore the library enforces a strict ordering:
- Configure the port once.
- Wait for the configuration to complete (
DONE=TRUE,ERROR=FALSE). - Begin issuing Modbus transactions; the master FB manages all frame timing internally.
Reconfiguring mid-traffic is a programming error, not a feature. The library does not prevent it; the user program must.
When to Set EN, COM_RST, and REQ
All three FBs use EN (enable) and REQ/COM_RST for different purposes. The lifecycle is:
| Phase | EN | COM_RST | REQ | OB |
|---|---|---|---|---|
| Cold/warm restart – initialise instance DBs | 1 | 1 (pulse one cycle) | 0 | OB 100 |
| Restart – apply port configuration | 1 | 0 (after pulse) | 1 (pulse one cycle) | OB 100 or first scan of OB 1 |
| Normal operation – poll slaves | 1 | 0 | 1 (continuous for each active master FB) | OB 1, cyclic |
| Recovery from fatal error | 1 | 1 (pulse), then 0 | 1 | OB 1 with error-handling logic |
EN – block enable
EN must be TRUE every time the FB is called. In ladder this is wired to a constant 1 or to the OB scan flag. The FB does no work when EN=FALSE; leaving it FALSE effectively disables the block.
COM_RST – instance reset
COM_RST is a level/edge input that clears the instance DB: pending frames are aborted, internal state machines return to idle, the port is forced back to its default (pre-configuration) settings. Use it:
- On cold/warm restart, typically in OB 100, to ensure no half-finished transactions from a previous run survive a reboot.
- After a fatal error that leaves the bus stuck (
STATUS=0x80C8or similar unrecoverable codes), to bring the FB back to a known state. - Never pulse it in normal cyclic OB 1 unless you are intentionally recovering from a fault – doing so will halt any active
MODBUS_MASTERtransaction.
REQ – execute / re-execute
For MODBUS_COMM_LOAD, REQ is a rising-edge trigger that re-applies the static configuration to the port. Apply it once after COM_RST has been released, then never again unless parameters change. A common pattern is to drive it from a one-shot (positive edge of a "first cycle" flag).
For MODBUS_MASTER, REQ controls transaction issuance. Two valid patterns exist:
-
Continuous polling: tie
REQ=TRUEpermanently; the FB auto-issues the next request as soon asDONE/ERRORfires andBUSYfalls. Use this when the cycle time to one slave is the desired refresh rate. -
Triggered polling: pulse
REQfrom a timer or event; the FB completes one transaction and waits for the next edge.
Step-by-Step: Correct Initialization on OB 100 + OB 1
The following sequence matches Siemens' recommended procedure for the S7-300/ET 200SP Modbus library.
Step 1 – Declare instance data blocks
For each call to MODBUS_COMM_LOAD and MODBUS_MASTER, declare a separate instance DB (e.g. DB_MB_LOAD, DB_MB_MASTER) and select "Instance" in the FB call. Multi-instance is also valid on S7-300/400 CPUs that support it.
Step 2 – OB 100 (startup)
In OB 100, on the first (and only) cycle:
- Set
MB_Load_COM_RST := TRUEandMB_Master_COM_RST := TRUEfor one cycle. - Reset the
MB_ConfigDoneandMB_MasterStartedflags.
Step 3 – OB 1, network 1: complete configuration
Wait for the COM_RST signals to return to FALSE (they self-clear inside the FB on the cycle after being processed), then pulse REQ on MODBUS_COMM_LOAD:
| --[ NOT MB_Load_COM_RST ]--[ NOT MB_Master_COM_RST ]--|
| [ MB_Load_DONE OR MB_Load_ERROR ]--[ MB_ConfigDone ]--|
| ( FP )-- MB_Load_REQ := TRUE
Wait for MB_Load_DONE=TRUE and latch MB_ConfigDone := TRUE. If MB_Load_ERROR=TRUE, capture MB_Load_STATUS and abort.
Step 4 – OB 1, network 2: poll slaves
Once MB_ConfigDone=TRUE, enable the master FBs:
- Set
MB_Master_REQ := MB_ConfigDone(continuous) or pulse from a timer. - Chain the FBs for the 10 slaves one after the other; only one transaction is active per scan because each FB sets
BUSY=TRUEuntil the response arrives.
Step 5 – Optional: watchdog
Start an IEC timer (e.g. TON with PT=5 s) on every REQ rise. If the timer expires without DONE or ERROR, pulse COM_RST on the affected FB and re-issue.
STATUS Code Reference
| STATUS (hex) | Source | Cause | Action |
|---|---|---|---|
0000 |
Both | No error. | None. |
80C8 |
Load / Master | Slave did not respond within RESP_TO. |
Check wiring, slave address, baud/parity. Increase RESP_TO. |
80D1 |
Load | Receive error: parity, framing, or overrun. | Verify parity matches slave; check for noise / ground shift; lower baud. |
80D2 |
Load | CTS timeout (RS-232 hardware flow control only). | Disable flow control or wire RTS/CTS correctly. For RS-485, set FLOW_CTRL=0. |
8180 |
Master | Invalid DATA_PTR or length out of range. |
Check pointer is non-NULL and length matches slave data type. |
8181 |
Master | Invalid MODE (function code) selected. |
Use a supported FC from the list above. |
818C |
Master | Pointer references a non-existent DB or wrong DB number. | Recreate the data DB and re-link DATA_PTR. |
80E0 |
Master | Message truncated (slave returned fewer bytes than requested). | Reduce DATA_LEN or fix slave register map. |
ET 200SP CM PtP Specific Notes
- The CM PtP module appears in the device view at a fixed slot (slot 1 by default). The HW identifier of the submodule providing the serial interface (e.g.
CM PtPrather than the interface module) is the one to use inPORT. - RS-485 mode requires the
FLOW_CTRL=0setting. Hardware flow control is RS-232 only. - Set the
RTS_OFF_DLYto a small positive value (e.g. 10 ms) if the bus master is unable to release the line cleanly between frames and slaves see residual characters. - The CM PtP requires firmware ≥ V2.0 for full Modbus RTU master support; older firmware only supports the ASCII variant. Verify with HW Config / device properties.
Verification
- Online: watch
MB_Load_STATUSreturn to0000after OB 100 and stay there. - Watch
MB_Master_BUSYtoggle TRUE while a transaction is outstanding and back to FALSE withinRESP_TO. - Confirm
MB_Master_DONEpulses once per successful transaction; count pulses in the online monitor – it should match the expected number of polls per second. - For 10 slaves at 9600 baud with FC 3 reads of 10 registers each, expect roughly 8 to 12 transactions per second, depending on slave response time.
- Disconnect one slave and confirm the FB returns
ERROR=TRUEwithSTATUS=0x80C8for that slave only, while the others continue.
Troubleshooting Matrix
| Symptom | Likely Root Cause | Fix |
|---|---|---|
All slaves time out, STATUS=80C8 after first transaction. |
MODBUS_COMM_LOAD never finished, port not configured. |
Check MB_Load_DONE; verify REQ pulsed; verify PORT HW identifier. |
| Communications work for a few seconds, then all fail. |
REQ of MODBUS_COMM_LOAD retriggering in OB 1. |
Move REQ generation behind a one-shot flag in OB 100 or first-scan logic. |
CRC errors or 80D1 on every transaction. |
Parity mismatch, baud mismatch, or A/B lines swapped. | Verify PARITY and BAUD against slave; swap A/B. |
First poll works, subsequent polls fail with 80E0. |
Slave drops connection on multi-register reads. | Reduce DATA_LEN; check slave's max PDU length (Modbus spec default 253 bytes). |
Master hangs with BUSY=TRUE forever. |
Lost response in noise; RESP_TO too long to be noticeable. |
Add a watchdog timer that pulses COM_RST on timeout. |
| ET 200SP station goes into diagnostic state when CM PtP errors. | Hardware fault (e.g. short on RS-485 bus). | Check 24 V supply to interface module; check for shield / ground loops; disconnect slaves one by one. |
Common Mistakes to Avoid
- Calling
MODBUS_COMM_LOADin OB 1 withREQdriven by a constant1. Every cycle reconfigures the port and corrupts frames. - Forgetting to pulse
COM_RSTon the first call after a download. The instance DB is freshly initialised but the underlying port state may still carry parameters from a previous project. - Sharing one instance DB between two
MODBUS_MASTERFBs. Each FB needs its own instance; otherwise the state machines collide. - Using
MW/QWaddresses inDATA_PTRthat overlap with the inputs of the FB itself – the FB will overwrite its own control bits. - Leaving
REQ=FALSEonMODBUS_MASTERafter start-up. The master will never issue a transaction.REQon the master is not a one-shot – it is the run enable.
Sample Ladder Snippet (S7-300, FBD-style)
Network 1 – OB 100 startup: pulse COM_RST
OB100_FIRST_CYCLE --[ P ]-- MB_LOAD_COM_RST
OB100_FIRST_CYCLE --[ P ]-- MB_MASTER_COM_RST
Network 2 – OB 1: trigger MODBUS_COMM_LOAD after COM_RST cleared
NOT MB_LOAD_COM_RST
AND NOT MB_MASTER_COM_RST
AND NOT MB_CONFIG_DONE
----------------------------------( P )-- MB_LOAD_REQ
Network 3 – OB 1: latch "configuration done"
MB_LOAD_DONE --[ S ]-- MB_CONFIG_DONE
MB_LOAD_ERROR --[ S ]-- MB_CONFIG_ERROR
Network 4 – OB 1: continuous master polling
MB_CONFIG_DONE
AND NOT MB_CONFIG_ERROR
--------------------------------------- MB_MASTER_REQ
FAQ
Should MODBUS_COMM_LOAD be called once in OB 100, or every cycle in OB 1?
Call it exactly once during startup, either from a startup OB (OB 100) or from a first-scan one-shot in OB 1. Per Siemens documentation, "execute it one time" – re-executing it reconfigures the port and breaks in-flight Modbus transactions.
What does the COM_RST input actually do?
COM_RST clears the FB's instance data block, aborts any in-flight Modbus frame, and forces the port back to its default (un-configured) state. Use it on cold/warm restart and after a fatal error; never pulse it in normal cyclic OB 1 unless you are intentionally recovering from a fault.
Why does my MODBUS_MASTER never poll cyclically even with REQ=TRUE?
The most common reason is that MODBUS_COMM_LOAD has not completed: MB_Load_DONE is still FALSE, so the underlying port is uninitialised. Verify the configuration block's DONE output and check STATUS for any error (e.g. invalid PORT identifier).
Is REQ on MODBUS_MASTER a one-shot or a level input?
It is edge-triggered for the start of a new transaction, but in continuous mode the FB internally re-arms it as soon as the current request finishes. In practice, drive REQ with the configuration-done flag and leave it TRUE.
How do I poll 10 slaves efficiently from one CM PtP?
Use 10 separate MODBUS_MASTER instance DBs, each configured for one slave, and chain them: while one FB is BUSY, the others wait in the ladder. This keeps the bus contention-free and the response timeouts independent per slave, which simplifies fault diagnostics.