Problem Definition
A SIMATIC S7-300 station equipped with a CP 340 point-to-point communication processor must exchange process data with a Delta Distributed Control System (DCS) over a serial line. The DCS exposes only a Modbus RTU slave port (RS-485 two-wire, 9600 bit/s, 8E1) for third-party integration. The engineering team wires the CP 340 to the DCS, installs the SIMATIC PtP library shipped with STEP 7 V5.x, calls FB 2 P_SEND and FB 3 P_RCV in OB1, and begins hand-rolling Modbus request telegrams: slave address, function code, starting register, quantity, payload, and a manually computed CRC-16.
The very first transaction returns "CRC error" on the DCS engineering station. The PLC transmits frames that look correct in a serial analyzer, but the DCS rejects every telegram. Retries with reversed byte order, swapped polynomial, and different initial values of the CRC register (0xFFFF vs 0x0000) do not clear the fault.
This is a deterministic outcome of the CP 340 hardware/firmware design: the CP 340 does not contain a Modbus RTU data link layer. There is no on-board CRC-16 generator, no inter-frame timer, no automatic function-code dispatch, and no slave address filtering. The only protocols burned into the CP 340 firmware are ASCII and 3964R. Any Modbus RTU behavior on the wire is being synthesized in the PLC scan, and that synthesis cannot meet the timing tolerances the Modbus specification requires.
Root Cause
The CRC error reported by the Delta DCS is the visible symptom. Three independent root causes are stacked beneath it:
- Protocol mismatch. The CP 340 firmware contains no Modbus RTU driver. Per the official CP 340 manual, the loadable drivers available for the module are ASCII, 3964R, and a printer driver; Modbus RTU master/slave is not on that list. See the protocol matrix in the Siemens CP 340 PtP documentation.
- CRC-16 implementation drift. Modbus RTU specifies CRC-16 with polynomial 0xA001 (reflected 0x8005), initial value 0xFFFF, and no final XOR. Common PLC implementations compute the CRC over the wrong byte range, swap the low and high bytes when transmitting, transmit the CRC big-endian instead of little-endian, or include the silent interval bytes in the CRC window. Each of these defeats the DCS check.
-
Inter-frame timing violations. Modbus RTU requires a 3.5 character silence to mark frame start and end, and frames must be transmitted as a contiguous stream. The PLC scan is non-deterministic (typically 10 to 80 ms); if the user program builds the telegram inside DBs and then hands it to
P_SEND, the bytes are buffered in the CP and emitted back-to-back, which is fine, but if the CRC is computed by user code in OB1 with multiple intermediate function calls, the CP 340's send buffer can be flushed in two segments separated by more than the 1.5 character inter-character threshold — causing the DCS to interpret the second half as a new, malformed frame.
CP 340 Hardware Identification
The CP 340 family is identified by MLFB (order number). Confirm the physical variant before any configuration work, because each interface type has different electrical limits and pin assignments.
| MLFB | Interface | Max Baud | Notes |
|---|---|---|---|
| 6ES7340-1AH02-0AE0 | RS-232C (V.24) | 19.2 kbit/s | TxD, RxD, RTS, CTS only — no Modbus |
| 6ES7340-1BH02-0AE0 | RS-485 (two-wire) | 9.6 kbit/s | Common choice for Modbus wiring, but firmware cannot run Modbus |
| 6ES7340-1CH02-0AE0 | RS-422 (four-wire) | 19.2 kbit/s | Full-duplex, point-to-point only |
Every variant above carries firmware that exposes only two protocol drivers: ASCII (transparent character mode with optional start/end characters and configurable fill time) and 3964R (Siemens proprietary SDLC-like protocol used between S5 and S7 partners).
Protocol Matrix — What CP 340 Will and Will Not Run
| Protocol | CP 340 native | CP 340 loadable | CP 341 native | CP 341 loadable |
|---|---|---|---|---|
| ASCII driver | Yes (FB 2 / FB 3) | — | Yes (FB 2 / FB 3) | — |
| 3964R | Yes (FB 2 / FB 3) | — | Yes (FB 2 / FB 3) | — |
| Printer driver | Yes (FB 4 / FB 5) | — | Yes | — |
| Modbus RTU master | No | Third-party only | No | Yes — dongle license required |
| Modbus RTU slave | No | Third-party only | No | Yes — dongle license required |
| RK512 / 3964R with RK512 | No | — | No | Yes — loadable driver |
The Modbus RTU master/slave driver for CP 341 is sold as a separate package (MLFB 6ES7870-1AA01-0YA0 historically; the current designation lives under the SIMATIC S7-300 communication catalog). It is delivered on a floppy / DVD and bound to the CP 341 by a license key / hardware dongle. Without that dongle present on the CP 341, the loadable driver will not initialize and the CP falls back to ASCII / 3964R only.
Modbus RTU Frame Structure Expected by the DCS
Before choosing a fix, document exactly what the Delta DCS expects. A Modbus RTU frame follows this layout:
| Slave ID | Function Code | Data Field | CRC-16 Lo | CRC-16 Hi |
| 1 byte | 1 byte | N bytes (variable) | 1 byte | 1 byte |
For function code 03 (Read Holding Registers), the data field contains a 2-byte starting address, a 2-byte quantity, and the CRC-16 is computed over the entire preceding bytes (slave ID through last data byte). For function code 06 (Write Single Register), the data field contains 2-byte address and 2-byte value. For function code 16 (Write Multiple Registers), the data field contains 2-byte starting address, 2-byte quantity, 1-byte byte count, N x 2-byte registers.
CRC-16 parameters:
- Polynomial: 0xA001 (reflected form of 0x8005)
- Initial value: 0xFFFF
- Final XOR: 0x0000
- Byte order on the wire: low byte first, then high byte
A reference CRC-16 routine in Structured Text is shown later in the article so that engineers can verify the calculation when debugging third-party packages.
Solution Path Selection
Three legitimate solutions exist, ranked by Siemens-preferred order:
- Path A — Upgrade to CP 341 with Modbus master/slave loadable driver. The supported, sanctioned path. Adds hardware cost and one-day commissioning but eliminates CRC and timing concerns.
- Path B — Negotiate ASCII protocol with the DCS. If the Delta DCS exposes a generic ASCII serial port (many Delta controllers offer both Modbus RTU and a free-form ASCII channel), the existing CP 340 can be used with no hardware change.
- Path C — Third-party Modbus RTU driver for CP 340. Available from independent vendors. Provides FB blocks similar to the CP 341 set. Siemens provides no support for these packages, and they often target a specific CP 340 firmware revision.
Solution Path A — Upgrade to CP 341 with Modbus Master
Hardware swap
- Power down the S7-300 rack.
- Remove the CP 340 module; preserve the backplane connector wiring list.
- Insert the CP 341 in the same slot. The CP 341 is pin-compatible at the backplane but requires its own MLFB per interface type:
- 6ES7341-1AH02-0AE0 — RS-232C
- 6ES7341-1BH02-0AE0 — RS-485 two-wire
- 6ES7341-1CH02-0AE0 — RS-422/RS-485 four-wire
- Order the loadable Modbus driver license (dongle) from your Siemens distributor. The license is hardware-bound; one dongle authorizes one CP 341 module.
- Wire the serial connector identically to the CP 340 wiring. RS-485 two-wire is the typical Modbus RTU wiring: A+ to DCS A+, B− to DCS B−, shield to ground at one end only, 120 Ω termination at each end of the trunk.
STEP 7 hardware configuration
- Open the SIMATIC Manager project containing the S7-300 station.
- In HW Config, delete the CP 340 from the rack and insert the CP 341 in the same slot.
- Double-click the CP 341 to open its properties dialog. Under Interface, select the protocol: Modbus Master (RTU) or Modbus Slave (RTU). The CP 341 will refuse to load the driver if the dongle is not detected.
- Configure the serial line parameters: 9600 bit/s, 8 data bits, even parity, 1 stop bit (8E1 is the most common Delta DCS setting; verify against the DCS documentation).
- Set the CP 341 diagnostic interrupts if you want OB82 to fire on line faults.
- Save and download the hardware configuration.
STEP 7 program structure with the Modbus master library
The loadable Modbus master driver exposes two FBs (block numbers vary by driver version; the modern designation is in the SIMATIC manual that ships with the dongle). The typical call pattern is:
// OB1 — cyclic call
CALL FB_MODBUS_MASTER, DB_MODBUS
REQ := M_REQ_START // start a single transaction
ID := 0 // logical CP 341 address (from HW Config)
slave_addr := MB_SLAVE_ID // 1..247, Delta DCS node
function := MB_FC_READ_HOLDING // 03, 06, 16 etc.
start_addr := MW_MODBUS_START // 0-based register offset
qty := MW_MODBUS_QTY // number of 16-bit registers
tx_data_ptr := P#DB_TX.DBX0 BYTE 32
rx_data_ptr := P#DB_RX.DBX0 BYTE 256
done := M_DONE
error := M_ERROR
status := MW_STATUS
The library handles CRC-16 generation, inter-frame silence, and response validation internally. The status word returned to MW_STATUS follows the Siemens Modbus master convention:
| Status (hex) | Meaning |
|---|---|
| 0x0000 | Idle / ready |
| 0x7000 | Job in progress |
| 0x0001 | Transaction complete, data valid |
| 0x8181 | Slave did not respond (timeout) |
| 0x8182 | CRC error in received frame |
| 0x8183 | Invalid function code from slave |
| 0x8184 | Invalid address from slave |
| 0x8185 | Invalid data value from slave |
| 0x8186 | Slave reports an exception (function code with high bit set) |
| 0x8187 | Memory allocation error in user DB |
| 0x8188 | Parity / framing error on the line |
Map each of these status codes to a tag in the PLC and to an alarm or HMI message so that operators can distinguish a real DCS fault from a wiring fault.
Solution Path B — ASCII Protocol to Delta DCS
Many Delta DCS controllers (e.g., DVP series PLC used as DCS node, or AH series with serial card) expose a configurable ASCII mode. In this mode the DCS sends and receives CR/LF-terminated text strings. The CP 340 handles ASCII natively with FB 2 P_SEND and FB 3 P_RCV; no CRC, no Modbus framing, no third-party driver.
Configure the CP 340 for ASCII
- In HW Config, double-click the CP 340, select protocol ASCII.
- Set baud rate to match the DCS (9600 8N1 is the typical default for Delta).
- Set end-of-receive delimiter: CR (0x0D) or LF (0x0A) — match the DCS configuration exactly. If both are required, set both.
- Set fill character delay if the DCS is slow (10 to 50 ms is common).
- Disable XON/XOFF and disable any 3964R-specific parameters.
Application frame
Define a fixed-format text protocol with the DCS team. Example for a periodic data push:
<STX>PLC1,AI01=23.45,AI02=110.2,DI01=1<CR><LF>
The CP 340 transmits the entire DB byte-for-byte; the receiving DCS parses the CSV fields. CRC is not part of the protocol — protect integrity with a checksum character at the end of the line or rely on the parity bit and the periodic retransmission.
Solution Path C — Third-Party Modbus RTU Driver for CP 340
Independent vendors sell a Modbus RTU master/slave package that loads into a CP 340. Search the SIMATIC third-party catalog or contact your Siemens distributor for the current options. Each package typically provides:
- A DLL / loadable firmware for the CP 340 module.
- Two FBs callable from OB1 (one for sending, one for receiving) — block numbers vary by vendor; some assign FB 42 / FB 43 in the user project as the suggested block numbers, others use FB 100+.
- An installation routine that registers the driver against a specific CP 340 firmware version (commonly 1.x and 2.x; check the matrix in the vendor's release notes).
Reference CRC-16 Routine for Diagnostic Use
When debugging a third-party driver or hand-rolled implementation, drop this Structured Text function into a STEP 7 SCL source file and call it from OB1 to compute the expected CRC of a buffer. Use it to compare against what arrives at the DCS or against what the CP transmits:
FUNCTION FC_CRC16 : WORD
VAR_INPUT
pData : POINTER TO BYTE;
iLen : INT;
END_VAR
VAR
i : INT;
j : INT;
crc : WORD;
b : BYTE;
END_VAR
BEGIN
crc := 16#FFFF;
FOR i := 0 TO iLen - 1 DO
crc := crc XOR WORD(pData^[i]);
FOR j := 0 TO 7 DO
IF (crc AND 16#0001) <> 0 THEN
crc := (SHR(crc,1) XOR 16#A001);
ELSE
crc := SHR(crc,1);
END_IF;
END_FOR;
END_FOR;
FC_CRC16 := crc;
END_FUNCTION
Test vector: 01 03 00 00 00 0A → CRC = C5CD, transmitted as CD C5 (low byte first).
Hardware Configuration Walk-Through (CP 340 ASCII Example)
- Open the STEP 7 project and load HW Config.
- Drag the CP 340 from the hardware catalog onto the S7-300 rack. Confirm slot number matches the physical module.
- Double-click the CP 340 → Properties. Set the interface to RS-485 if the DCS uses two-wire Modbus or to RS-232C for point-to-point ASCII.
- Select protocol ASCII. (The Modbus RTU option will not appear — this is the confirmation that the CP 340 cannot do Modbus natively.)
- Configure baud rate, parity, data bits, stop bits to match the DCS.
- Set the start-of-receive trigger if the DCS sends framing characters; otherwise leave blank.
- Assign the CP 340 to a logical interrupt OB if you need immediate notification of receive events (OB40).
- Save, compile, download to the PLC. The CP 340 will not initialize until the configuration is downloaded.
Program Structure (CP 340 ASCII Path)
// OB1 — cyclic
// Build outbound data in DB100
L DB100.DBB0 // first byte
T DB110.DBB0 // mirror to send buffer
// ... copy full payload ...
// Trigger send
A M 10.0 // rising edge trigger from HMI or sequencer
= L 0.0
A L 0.0
FP M 10.1
= M 10.2
CALL FB 2, DB20
REQ := M10.2
ID := 0 // logical CP address from HW Config
LADDR := W#16#100 // I/O base address of CP 340
DB_NO := 110 // DB containing send buffer
DBB_NO:= 0 // start byte offset in DB110
LEN := 64 // byte count
DONE := M20.0
ERROR := M20.1
STATUS:= MW22
// Receive
CALL FB 3, DB21
EN := TRUE
ID := 0
LADDR := W#16#100
DB_NO := 111 // receive DB
DBB_NO:= 0
LEN := 256 // max buffer length
NDR := M21.0 // new data received
ERROR := M21.1
STATUS:= MW23
LEN_OUT:= MW24 // actual byte count received
RS-485 Wiring Notes for Modbus / ASCII to Delta DCS
| CP 340 / 341 RS-485 pin | Signal | Delta DCS terminal |
|---|---|---|
| Pin 4 (T/B) | Data A+ | D+ / A |
| Pin 8 (R/A) | Data B− | D− / B |
| Pin 1 (Shield) | Cable shield | FG (ground at DCS end only) |
| — | 120 Ω termination | Install at CP end and at far DCS end if bus > 10 m |
Do not ground the shield at both ends — this creates a ground loop that injects common-mode noise and corrupts bytes, surfacing as CRC errors or framing errors.
Verification and Commissioning
- With the CP powered and configured, check HW Config → Online → Module Information. Confirm the diagnostic buffer shows no entry of type Module fault or Parameter assignment error.
- From the STEP 7 online portal, open Monitor/Modify on the CP 340/341 diagnostic tags. Verify the line status (line idle, no break, no framing errors).
- Connect a serial analyzer (or use a passive tap) between the CP and the DCS. Capture the first 10 transactions. Confirm byte timing and CRC visually.
- Trigger a single read transaction from the PLC. Verify the
DONEflag rises, theSTATUSword is 0x0001, and the receive DB contains the expected register values mapped to the Delta DCS tag. - Trigger a single write transaction (function code 06 or 16). Read the same register back from the DCS to confirm the write landed.
- Run the link under full PLC scan load for at least 30 minutes; verify no CRC errors appear in the CP diagnostic buffer or in the DCS event log.
- Force a DCS-side slave fault (disconnect the A wire momentarily) and confirm the PLC
ERRORflag rises within the configured response timeout and theSTATUSword returns 0x8181 or the equivalent for your driver.
Troubleshooting Matrix
| Symptom | Likely Cause | Action |
|---|---|---|
| DCS reports CRC error on every transaction | Modbus RTU being synthesized by hand in CP 340 user program | Switch to CP 341 with Modbus driver, or use ASCII path, or install third-party Modbus driver |
| DCS reports CRC error intermittently | Inter-character gap exceeding 1.5 char due to PLC scan segmentation | Build the full Modbus frame in a contiguous DB and trigger P_SEND once |
| No response from slave (timeout) | Wrong slave ID, swapped A/B wires, baud rate mismatch | Capture on analyzer; verify single-byte echo of slave ID; check A+ and B− polarity against DCS pinout |
| Parity / framing error in CP diagnostic buffer | Parity mismatch, stop bit mismatch, baud rate off by factor of 2 | Match DCS settings exactly; verify with analyzer at both ends |
| CP 341 Modbus driver will not load | License dongle missing or wrong MLFB | Insert correct dongle; verify in HW Config that the CP 341 shows the driver as licensed |
| STATUS = 0x8182 (CRC error in received frame) | Line noise, missing termination, ground loop on shield | Add 120 Ω at both ends; ground shield at DCS only; check for VFD-induced noise if motor cables run parallel |
| STATUS = 0x8186 (slave exception) | DCS rejects function code or address range | Check DCS Modbus address map; confirm register range is readable/writable from the DCS side |
| Intermittent good and bad transactions | Duplicate slave ID on the bus | Confirm each node has a unique Modbus address 1..247 |
| Receive buffer empty though analyzer shows traffic | ASCII end-of-receive character not configured | Set CR / LF delimiter to match DCS; if DCS uses no delimiter, set fixed length or character timeout |
Choosing Between the Three Paths
| Criterion | Path A: CP 341 + Modbus | Path B: ASCII | Path C: 3rd-party Modbus on CP 340 |
|---|---|---|---|
| Siemens support | Full | Full | None from Siemens |
| Hardware cost | CP 341 + dongle license | None (re-use CP 340) | None (re-use CP 340) |
| Engineering effort | Low — loadable driver | Medium — define text protocol with DCS team | Medium — driver install, version pinning |
| CRC integrity | Hardware-managed | Not used (ASCII) | Driver-managed |
| Risk on STEP 7 upgrade | Low | Low | High — driver may not survive firmware change |
| Performance (transactions/sec) | High — 30 to 50/s typical | Medium — limited by line discipline | High |
For most brownfield integration projects where the Delta DCS is fixed and only exposes Modbus RTU, Path A is the correct answer. The cost of a CP 341 plus license is small compared to weeks of debugging hand-rolled CRC code on the CP 340, and the result is a Siemens-supported, deterministic link.
FAQ
Does the Siemens CP 340 support Modbus RTU natively?
No. The CP 340 firmware includes only the ASCII and 3964R drivers. Modbus RTU master or slave on a CP 340 requires either a third-party loadable driver (no Siemens support) or a hardware upgrade to a CP 341 with the Modbus master/slave loadable driver and license dongle.
Why does the Delta DCS report a CRC error on every Modbus request from the CP 340?
Because the CP 340 has no on-board Modbus RTU data link layer. The CRC-16, inter-frame silence, and slave address filtering must all be implemented in the PLC user program, and small differences in byte order, polynomial application, or transmit timing produce a CRC that does not match the DCS expectation. The supported fix is to swap the CP 340 for a CP 341 and load the Modbus master driver.
Which FBs do I call to send and receive with the CP 340?
For ASCII and 3964R use FB 2 P_SEND and FB 3 P_RCV from the SIMATIC PtP library. For Modbus RTU on a CP 341, call the FBs shipped with the Modbus master loadable driver (commonly designated P_SND_MB / P_RCV_MB in current documentation; check the manual that ships with the dongle for exact block numbers and the call interface).
What are the common CP 340 / CP 341 MLFBs and how do they differ?
CP 340: 6ES7340-1AH02-0AE0 (RS-232C), 6ES7340-1BH02-0AE0 (RS-485 2-wire), 6ES7340-1CH02-0AE0 (RS-422/485 4-wire). CP 341: 6ES7341-1AH02-0AE0, 6ES7341-1BH02-0AE0, 6ES7341-1CH02-0AE0 for the same three interface options. Both modules are S7-300 plug-in design and are pin-compatible at the backplane.
Can I keep the CP 340 and talk to the Delta DCS in ASCII instead of Modbus RTU?
Yes, if the Delta DCS supports a generic ASCII mode with CR/LF-terminated strings. Configure the CP 340 to the ASCII driver, match baud rate and parity to the DCS, and define a simple comma-separated or tag-based text protocol. This avoids Modbus framing entirely but requires agreement on the text format with the DCS engineering team.