1. Overview
The CP 341 communication processor is a serial point-to-point module for SIMATIC S7-300 (and ET 200M in PCS 7) that hosts the licensed Modbus Master RTU driver. The driver is implemented as a loadable firmware on the CP 341 and exposes two standard function blocks on the CPU side: FB 8 "P_SND_RK" for sending Modbus request frames and FB 7 "P_RCV_RK" for receiving response frames. Together they form the deterministic, half-duplex master layer for polling up to 247 Modbus RTU slaves on RS-232 or RS-485.
This reference documents a working PCS 7 V9.0 implementation that polls five Modbus RTU slaves using OB 32 as the cyclic dispatcher, DB 10 as the rotating parameter set, and DB 11 as the rolling receive buffer. It also clarifies how the NDR output of FB 7 behaves when a slave fails to respond, and how to detect that condition without losing the master state machine.
2. Hardware Selection and Wiring
For PCS 7 V9.0 with five slaves on a single bus, the practical hardware choice is the RS-485 variant of the CP 341. RS-485 supports multi-drop, longer cable runs, and proper bus termination that RS-232 cannot provide.
| MLFB | Interface | Max Distance | Use Case |
|---|---|---|---|
| 6ES7341-1AH02-0AE0 | RS-232C (V.24) | 15 m | Single-drop, point-to-point |
| 6ES7341-1CH02-0AE0 | RS-422 / RS-485 (X27) | 1200 m @ 9600 bps | Multi-drop Modbus RTU bus |
For an RS-485 bus, observe the following physical rules:
- Terminate both ends of the trunk with 120 Ω resistors between the data lines (P and N). The CP 341 RS-485 variant includes a slide switch on the front connector to enable the internal termination.
- Never put termination in the middle of the bus; only at the physical extremes.
- Use twisted-pair cable with shield grounded at one end only (typically the cabinet ground).
- Set the cable shield to FE on the CP end; do not loop it back to multiple grounds.
- Limit stubs (drop cables) to less than 30 cm. Daisy-chain from CP → slave 1 → slave 2 → slave 3 → slave 4 → slave 5 → termination.
3. Software Stack and Licensing
The Modbus Master RTU driver is loaded onto the CP 341 once, using the SIMATIC Manager / PCS 7 Engineering "Modbus Master CP341" parameterization tool. The license is bound to the CP's serial number and survives firmware updates as long as the hardware is not replaced.
| Component | Version | Purpose |
|---|---|---|
| STEP 7 / PCS 7 Engineering | V9.0 (or compatible V9.0 SPx) | Hardware config, FB library, DB generation |
| CP 341 Modbus Master RTU driver | V3.x (driver CD shipped with module or download) | Loads Modbus protocol stack on CP firmware |
| Modbus Master license | Per-CP, model 6ES7341-1CH02-0AE0 | Unlocks the RTU master firmware |
| CP 341 firmware | FW 2.x (depending on driver rev.) | CP base firmware, required by driver |
After loading the driver, the CP 341's online diagnostics ("Diagnostic buffer of the CP") will report "Modbus Master RTU active". Until the driver is loaded, FB 7/FB 8 calls will return STATUS = W#16#818C ("CP not ready").
4. CP 341 Configuration in HW Config
Insert the CP 341 in the S7-300 rack at the slot planned for it (typically slot 4 through 11, depending on the CPU and existing modules). In the object properties, set:
| Parameter | Recommended Value | Notes |
|---|---|---|
| Protocol | Modbus Master RTU | Selectable only if driver is licensed |
| Baud rate | 9600 bps (start) → 19200 bps typical | Must match all slaves |
| Data bits | 8 | RTU fixed |
| Parity | Even (preferred for legacy RTU) or None | Match slave configuration exactly |
| Stop bits | 1 (with Even/None parity) or 2 | Match slave configuration exactly |
| Flow control | None | RTU does not use RTS/CTS for slave polls |
| Reply monitoring time | 2000 ms (adjust per baud) | 3.5 char minimum silence, driver uses calculated time |
| Character delay time | 4 ms typical | Inter-character timeout (1.5 char time at given baud) |
5. Modbus Master Driver Configuration
Open the CP 341's "Protocol" object. The dialog lets you assign a Modbus Master configuration block. This is a DB that the driver parses on power-up to know which slave polling pattern to run automatically. In PCS 7 V9.0, the typical approach is to leave the CP in "Driver-controlled" mode and dispatch from the CPU via FB 7/FB 8 instead, giving the application full control of which slave is queried when.
The application-controlled pattern works as follows:
- The CPU writes the next Modbus request (slave address, function code, register offset, register count) into a shared parameter DB (here DB 10).
- The CPU calls FB 8 (P_SND_RK) with the parameter DB reference. The CP transmits the request on the wire.
- The CPU calls FB 7 (P_RCV_RK) on the same LADDR. When the CP has assembled a complete response, FB 7 returns NDR = TRUE and writes the response into a receive DB (here DB 11) at the offset supplied via
DBB_NO. - The application interprets the response, advances state, and after a defined inter-frame delay repeats for the next slave.
6. Function Block Architecture (FB 7 / FB 8)
FB 8 (P_SND_RK) and FB 7 (P_RCV_RK) live in the standard SIMATIC library under "Communication Blocks". They are instance-free (use the standard instance DBs that the library assigns automatically) and are called from OB 1 in this implementation:
- FB 8 — P_SND_RK: Sends a Modbus request buffer to the CP. Triggers the CP to transmit the request on the bus.
- FB 7 — P_RCV_RK: Reads the response buffer assembled by the CP. Returns NDR when a new response has been received since the last call.
Both blocks share the same LADDR input (the I/O base address of the CP 341 in HW Config). Calling FB 7/FB 8 with a different LADDR than the CP's logical base address will silently fail with STATUS = W#16#8183 or W#16#818C.
7. FB 8 P_SND_RK Parameterization
Wire FB 8 as follows. Inputs marked constant should be declared as local constants in the calling FC 10 to keep OB 1 clean.
| Input | Type | Value | Description |
|---|---|---|---|
| SF | BOOL | M10.0 | Send trigger. Edge from 0→1 starts a send job. |
| LADDR | INT | 256 (example) | CP 341 logical base address from HW Config. |
| DB_NO | INT | 10 | DB containing the Modbus request payload (slave ID, FC, offset, count). |
| DBB_NO | INT | 0 | Byte offset in DB 10 where the request starts. |
| LEN | INT | 8 | Length of the request buffer (typically 8 bytes for a single read/write). Range 1–4096. |
| R | BOOL | FALSE | Reset/abort the job. Not used in steady-state operation. |
The output DONE (here M10.1) signals successful transmission. A negative edge on DONE is the natural moment to clear the SF trigger.
8. FB 7 P_RCV_RK Parameterization
FB 7 reads the response that the CP 341 has buffered since the last successful send.
| Input | Type | Value | Description |
|---|---|---|---|
| EN_R | BOOL | TRUE | Enable receiver — must stay TRUE for the block to fetch data. |
| R | BOOL | FALSE | Receiver reset (rarely used; clears the internal NDR latch). |
| LADDR | INT | 256 (same as FB 8) | CP 341 logical base address. |
| DB_NO | INT | 11 | Receive data DB. |
| DBB_NO | INT | 0 / 32 / 64 / … | Offset in DB 11. Increment per slave to keep a rolling buffer. |
| LEN | INT | Variable | Max receive length. Must be ≥ actual response length. |
The two outputs you monitor are:
- NDR (New Data Ready) — pulses TRUE for one cycle when a complete response has been fetched. This is the application-level "slave answered" signal.
- ERROR + STATUS — surfaces Modbus errors, frame errors, timeouts, and CP errors.
9. OB 32 Cyclic Polling Implementation
OB 32 in PCS 7 runs at a configurable base time. The recommended base for Modbus RTU at 9600 baud with 5 slaves is 1 s; the implementation in question uses a 5 s phase to be conservative on slow slaves. The OB 32 logic is the rotating index over the five slaves.
Pseudo-code for OB 32 (SCL-style for readability, equivalent ladder exists):
// State variable in a global DB
iSlaveIdx := (iSlaveIdx + 1) MOD 5;
// Populate DB 10 from a static array of 5 slave descriptors
DB10.SlaveAddr := SlaveDesc[iSlaveIdx].Addr; // e.g. 1..5
DB10.FunctionCode := SlaveDesc[iSlaveIdx].FC; // e.g. 03 = Read Holding
DB10.StartAddr := SWAP_WORD(SlaveDesc[iSlaveIdx].Reg); // Modbus is big-endian
DB10.Quantity := SWAP_WORD(SlaveDesc[iSlaveIdx].Qty);
DB10.ByteCount := SlaveDesc[iSlaveIdx].Qty * 2;
DB10.RequestLen := 8;
DB10.ReceiveOffset := iSlaveIdx * 64; // 64 bytes per slot in DB 11
// Arm the send trigger for OB 1
M10.0 := TRUE;
// Latch the OB 32 "ready" flag so OB 1 knows DB 10 has been refreshed
M11.0 := TRUE;
OB 1 calls FC 10, which in turn calls FB 8 and FB 7 in the sequence:
// FC 10 (called from OB 1)
IF M11.0 THEN // OB 32 just refreshed DB 10
FB8.DB_NO := 10;
FB8.DBB_NO := 0;
FB8.LEN := DB10.RequestLen;
FB8.SF := M10.0; // rising edge starts send
FB8.LADDR := 256;
IF M10.1 THEN // send done (DONE flag)
M10.0 := FALSE; // clear trigger (negative-edge clear in OB 1)
FB7.EN_R := TRUE;
FB7.DB_NO := 11;
FB7.DBB_NO := DB10.ReceiveOffset;
FB7.LEN := 256; // receive buffer max
END_IF;
IF FB7.NDR THEN // response received
// parse DB11 starting at DB10.ReceiveOffset
M11.0 := FALSE; // clear "OB 32 ready" flag
END_IF;
END_IF;
10. Multi-Slave Data Structure
The recommended layout is a single DB 10 holding the active request (8 bytes + 1 length byte) and DB 11 holding the rolling response buffer with one fixed slot per slave. This keeps OB 32 trivial and makes commissioning differences between slaves easy to diagnose.
10.1 DB 10 — Active Request
| Offset | Symbol | Type | Description |
|---|---|---|---|
| 0.0 | SlaveAddr | BYTE | 1..247 (Modbus RTU address) |
| 1.0 | FunctionCode | BYTE | 01/02/03/04/05/06/15/16 |
| 2.0 | StartAddr | WORD | Register offset, high-byte first (big-endian) |
| 4.0 | Quantity | WORD | Number of registers or coils |
| 6.0 | ByteCount | BYTE | Quantity × 2 (read holding/input) or quantity ÷ 8 (read coils) |
| 7.0 | RequestLen | BYTE | Length of the request frame on the wire |
| 8.0 | ReceiveOffset | INT | Slot in DB 11 to write the response |
10.2 DB 11 — Rolling Response Buffer
Each slave occupies a 64-byte slot. Five slaves = 320 bytes. Reserve at least 8 bytes of header inside each slot for the parsed fields (slave address echo, FC echo, byte count, CRC status, timestamp).
| Slot | Offset | Contents |
|---|---|---|
| Slave 1 | 0..63 | Parsed response 1, timestamp, status |
| Slave 2 | 64..127 | Parsed response 2, timestamp, status |
| Slave 3 | 128..191 | Parsed response 3, timestamp, status |
| Slave 4 | 192..255 | Parsed response 4, timestamp, status |
| Slave 5 | 256..319 | Parsed response 5, timestamp, status |
11. Slave Failure Detection via NDR
There are three failure modes to handle explicitly. The NDR signal alone is insufficient — it must be paired with a watchdog and an explicit "expecting response" flag.
11.1 Slave does not respond (timeout)
Symptom: SF rises → DONE rises (request transmitted) → NDR never rises → STATUS stays at W#16#7000.
Detection: Start a TON timer (e.g., 500 ms above the CP's configured reply monitoring). If the timer elapses without NDR, set a "slave N comm fault" flag.
11.2 Slave responds with Modbus exception
Symptom: NDR rises, but the FC byte in the response has bit 7 set (e.g., 0x83 instead of 0x03). The exception code in the next byte indicates ILLEGAL FUNCTION (01), ILLEGAL DATA ADDRESS (02), ILLEGAL DATA VALUE (03), etc.
Detection: After NDR, inspect the FC byte. If FC >= 0x80, branch into the exception handler and surface the exception code in a global alarm DB.
11.3 Slave responds with corrupt frame (CRC error)
Symptom: CP rejects the frame internally; FB 7 raises STATUS = W#16#8187 (frame error) instead of NDR.
Detection: Treat STATUS > W#16#8180 as a transport-level fault, do not advance the state machine, and log the slave ID + STATUS value.
Suggested watchdog implementation in FC 10:
// Run only while a response is expected
IF M10.1 AND NOT M10.6 THEN // sent but not yet received
iWatchdog := iWatchdog + 1;
IF iWatchdog > 50 THEN // 50 × 100 ms = 5 s
bSlaveFault[DB10.SlaveAddr] := TRUE;
M11.0 := FALSE; // advance to next slave anyway
M10.0 := TRUE; // arm next poll cycle
iWatchdog := 0;
END_IF;
ELSE
iWatchdog := 0;
END_IF;
12. Modbus Exception Code Mapping
When a Modbus slave answers with an exception, the response FC byte has the high bit set (0x80 OR'd with the original FC) and a one-byte exception code follows. The application must decode this and surface it to the operator.
| Code | Name | Typical Cause in PCS 7 Polling |
|---|---|---|
| 01 | ILLEGAL FUNCTION | Slave does not support the FC; e.g. attempting FC 06 write single register on a read-only meter. |
| 02 | ILLEGAL DATA ADDRESS | StartAddr in DB 10 is outside the slave's address map; offset the request by the slave's Modbus register base. |
| 03 | ILLEGAL DATA VALUE | Quantity > allowed max, or write value outside valid range. |
| 04 | SLAVE DEVICE FAILURE | Internal slave error while processing; retry once with backoff before raising an alarm. |
| 05 | ACKNOWLEDGE | Long-running command accepted but not complete; poll again after a delay. |
| 06 | SLAVE DEVICE BUSY | Retry with exponential backoff. |
| 08 | MEMORY PARITY ERROR | Slave internal memory fault — escalate to maintenance. |
| 0A | GATEWAY PATH UNAVAILABLE | Router / gateway behind the slave is offline. |
| 0B | GATEWAY TARGET NO RESPONSE | Downstream device behind the gateway did not respond. |
13. Status and Error Code Reference
The following STATUS codes are surfaced on FB 7 and FB 8 when the Modbus Master RTU driver is loaded. They are returned in W#16# notation and should be mapped 1:1 into an operator-visible diagnostic block.
| STATUS | Block | Meaning | Recommended Action |
|---|---|---|---|
| 0000 | Both | Job completed without error | None |
| 7000 | Both | No job active / receiver idle | Normal idle state |
| 8181 | SND/RCV | Length mismatch between SD and LEN | Correct LEN parameter |
| 8182 | SND/RCV | DB too short or DB number 0 | Increase DB length; verify DB_NO |
| 8183 | SND/RCV | Parameter assignment error (e.g. wrong LADDR) | Re-check CP slot and LADDR |
| 8184 | RCV | Modbus exception in response | Inspect exception code in DB 11 |
| 8185 | RCV | Reply timeout — slave did not respond | Check slave power, address, baud |
| 8186 | RCV | Negative acknowledgment from CP | Re-initialize CP |
| 8187 | RCV | Frame error (invalid stop bits, framing) | Match baud/parity/stop bits to slave |
| 8188 | RCV | Parity error | Match parity; check cable |
| 8189 | RCV | Overrun error | Reduce baud rate or inter-frame spacing |
| 818A | RCV | Receive buffer overflow | Increase LEN or reduce slave response size |
| 818B | SND | CP internal parameter error | Reload driver firmware |
| 818C | Both | CP not ready / driver not loaded | Load Modbus Master RTU driver |
| 818D | SND | L_TW mismatch | Match LEN to actual buffer length |
14. OB 32 / OB 1 Timing
The following diagram illustrates the interlock between OB 32 (slow dispatcher) and OB 1 (fast driver caller). The 5 s phase is the OB 32 base time; the actual Modbus cycle is on the order of 50–200 ms at 9600 baud.
15. Troubleshooting Matrix
| Observed Symptom | Likely Cause | Diagnostic Step | Fix |
|---|---|---|---|
| Every send returns W#16#818C | Modbus Master driver not loaded | CP online diagnostics → Operating Mode | Re-load driver, verify license |
| DONE rises but NDR never rises, STATUS = 7000 | Slave power off / wrong address / wrong baud | Modbus scanner tool on the bus | Confirm slave power, address DIP, baud match |
| NDR rises with FC byte ≥ 0x80 | Modbus exception | Read exception code byte | Correct StartAddr, Quantity, or FC choice |
| STATUS = W#16#8187 (frame error) on every poll | Baud / parity mismatch | Verify slave configuration register | Adjust CP protocol parameters in HW Config |
| STATUS = W#16#8188 (parity error) sporadic | Electrical noise / long cable / no termination | Oscilloscope on bus | Enable termination, check shield, shorten stubs |
| STATUS = W#16#8185 (timeout) on slave 3 only | Slave 3 address conflict or removed from bus | Disconnect slaves one by one | Fix addressing or restore slave |
| OB 32 fires but DB 10 unchanged | Index not advancing, MOD operation broken | Online watch iSlaveIdx in VAT | Check MOD boundary; ensure integer variable is reset on restart |
| CPU scan time increase after enabling CP | FB 7 / FB 8 executed every cycle | OB 1 time stamp delta | Gate FB calls behind M11.0 to save CPU |
| Receive data scrambled between slaves | DBB_NO not updated per slave | Watch DB 11 in VAT | Recompute ReceiveOffset = iSlaveIdx × 64 in OB 32 |
16. Verification and Commissioning Procedure
- Driver load verification: In HW Config, open the CP 341 → "Operating Mode" → confirm "Modbus Master RTU driver loaded". Without this, every send returns W#16#818C.
- Loopback test: Connect the CP 341 RS-485 ports together (T/R+ ↔ T/R- on both ends) with a short jumper. Run the master against slave address 1 with FC 03 reading 1 register from offset 0. The CP will echo its own request; the CRC will fail and STATUS = W#16#8187. This confirms wiring and baud, isolating it from the slaves.
- Single-slave test: Connect one known-good slave (e.g., a Modbus simulator or a Schneider electric meter). Confirm NDR pulses and STATUS = W#16#0000 on the first request.
- Multi-slave sequential test: With OB 32 stepping through five slaves at 5 s, observe the slave LED activity on each physical device. Each slave should see one request per cycle of five phases.
- Negative test: Power down slave 3. Confirm that the master continues polling slaves 1, 2, 4, 5 and that the slave 3 fault flag sets within the configured watchdog window.
- Watchdog boundary test: Reduce the slave reply time below the CP's configured reply monitoring to force STATUS = W#16#8185. Verify the application flags the correct slave and recovers automatically when the slave reappears.
- Long-run stability: Run for 24 h, log all STATUS values to a circular buffer, and verify zero unexpected codes.
- CPU scan budget: Profile OB 1 with FB 7 + FB 8 active. The blocks add roughly 1–3 ms per call to the scan. At 5 s OB 32 phase this is negligible; at 100 ms phase it becomes visible and should be re-measured.
- WinCC faceplate check: If the Modbus data drives a WinCC faceplate, verify the scaling block (engineering units → raw 0–27648 or floating point) is correct on each faceplate instance, and that the value is being read from the right DB 11 slot.
17. Related Siemens Documentation
For reference, the SIMATIC Modbus documentation set shipped with the driver and the TIA Portal documentation portal cover the same FBs from a different angle. The MODB_341 instruction, for example, is the modern equivalent used when the CP is configured via TIA Portal V20 instead of STEP 7 V5 / PCS 7:
The PCS 7 V9.0 / STEP 7 V5.6 path uses FB 7 / FB 8 (P_SND_RK / P_RCV_RK) and is documented in the Modbus Master CP 341 manual that ships on the driver CD (Siemens/Documentation shortcut after install).
18. Frequently Asked Questions
Can FB 8 and FB 7 be called from OB 1 directly, or do they need an instance FC?
Yes — calling them from OB 1 directly is the standard pattern. The "instance" in this case is the standard instance DB the library assigns to each block. Using an intermediate FC 10 only helps keep OB 1 readable and provides one place to put the negative-edge logic for clearing M10.0.
Is the NDR bit on FB 7 sufficient to detect a failed slave?
No. NDR only pulses when the CP successfully receives and validates a frame. A non-responsive slave never causes NDR to rise. You must pair FB 7 with a watchdog timer started when the send completes (DONE = TRUE) and not reset until NDR arrives. If the watchdog expires before NDR, that is your slave-failed condition.
Why does STATUS stay at W#16#7000 even though the slave is wired and powered?
W#16#7000 on FB 7 means the receiver is idle — no new data has been assembled since the last read. This is normal between Modbus cycles. If it stays 7000 forever and NDR never rises, the most likely cause is that FB 8 never actually transmitted: check that SF produced a real rising edge, that LADDR matches the CP slot, and that the CP's driver is loaded (otherwise STATUS on FB 8 would be W#16#818C).
Do I need the Modbus Master RTU driver license?
Yes. The Modbus Master RTU driver is a separately licensed firmware that must be loaded onto the CP 341. The CPU-side FB 7 / FB 8 blocks are part of the standard library and do not require a runtime license; the license is bound to the CP's serial number.
What is the maximum number of slaves I can poll with a single CP 341?
The Modbus RTU standard supports up to 247 slaves per bus. Practical limits on a CP 341 are: baud rate (higher baud = faster cycle but shorter cable), slave response size, and CPU scan budget. With five slaves and a 5 s OB 32 phase the bus is essentially idle 99 % of the time, so a single CP 341 can comfortably poll 20–30 slaves at 9600 baud with sub-second effective cycle.
Can the same CP 341 run Modbus Master RTU and Modbus Slave RTU simultaneously?
No. A CP 341 loaded with the Modbus Master RTU driver is a master only. To run as a slave, reload the CP with the Modbus Slave RTU driver, which exposes the MODB_341 instruction on the CPU side instead of FB 7 / FB 8.