S7-1200 CM1241 Modbus RTU: Fix SEND_PTP 00 Header Byte

David Krause15 min read
S7-1200SiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Problem Overview: S7-1200 CM1241 Communicating with Custom PCBs over RS485

A standard integration task in building automation is wiring a SIMATIC S7-1200 CPU (for example, CPU 1215C) to a population of custom printed circuit boards (PCBs) that control doors and lights. Each PCB is a node on a single RS485 bus, addressed by Modbus, programmed in C on the embedded side. The first implementation hurdle is normally protocol selection (RTU vs. ASCII vs. raw point-to-point), but a much more common field failure appears once the engineer starts sending the first bytes from the PLC: a stray 00 (or other) header byte is prepended to every transmit buffer.

This article documents the diagnostic path, the two proven workarounds, the electrical prerequisites (termination, bias, common-mode range), and the verification procedure for a stable link. It assumes the PLC side is programmed in TIA Portal V16 or later and that the CM 1241 RS422/485 (6ES7241-1CH32-0XB0) communication module is installed to the left of the CPU.

Field note. The "00 header" symptom is almost always a configuration artifact of Port_Config and Send_Config defaults, not a hardware defect. Replace the configuration pair first; replace the module last.

CM 1241 RS422/485 Hardware Reference

The CM 1241 RS422/485 is a 9-pin sub-D female serial module. The values below are taken from the SIMATIC S7-1200 Programmable Controller System Manual collection. Use them for the bill of materials, the cabinet layout, and the EMC checklist.

CM 1241 RS422/485 key specifications
Parameter Value
Order number (6ES7241-1CH32-0XB0) RS422/485, 9-pin sub-D female
Supported modes RS422 (4-wire full duplex) and RS485 (2-wire half duplex)
Common-mode voltage range -7 V to +12 V, 1 second; 3 V RMS continuous
Baud rates 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200 bit/s
Maximum cable length 1000 m (RS485, 9600 bit/s, terminated)
Maximum number of nodes 32 nodes per segment (RS485 load units)
Termination External 120 Ω between A and B, switchable via DIP on some revisions
Isolation Galvanic to backplane; functional isolation between signal pairs

Reference: CM 1241 RS422/485 Specifications — SIMATIC S7-1200 Manual Collection.

RS485 Wiring Topology and 4-Wire vs. 2-Wire Decision

Modbus over RS485 in building automation is virtually always 2-wire half duplex (a single twisted pair, A and B, plus a common return). A 4-wire RS422 channel can be operated as 2-wire RS485 by tying TX+ to RX+ (signal name A) and TX- to RX- (signal name B) at the PLC end. The fourth and fifth conductors normally found in a 4-wire cable are therefore not used for signal but for shielding and ground:

  1. Pair 1 (twisted): A (D+) and B (D-). Modbus data.
  2. Pair 2 (twisted): Common/Signal Ground (GND) and Cable Shield (drain).

Recommended cable: Belden 3106A or equivalent, 120 Ω characteristic impedance, 24 AWG, foil + braid shield. The shield must be bonded to ground only at one end of the segment to avoid ground-loop currents; in noisy industrial cabinets, a short pigtail to a clean ground bar is preferred.

Modbus RTU vs. ASCII vs. Raw PtP

The decision on the bus framing is the single most important architecture choice. TIA Portal V16+ provides three layers that the engineer can stack on top of the CM 1241:

Framing options on CM 1241
Option Block family Best for Header / framing overhead
Modbus RTU master MB_COMM_LOAD, MB_MASTER (FC 01-06, 15, 16, 23) Mixed-vendor slaves, long service life, standard diagnostics 3.5-char inter-frame silence, CRC16
Modbus ASCII Same block family, ASCII mode Human-readable debug, slow lines, telecom-style devices ':' start, CRLF, LRC8
Raw point-to-point (PtP) Port_Config, Send_Config, Send_P2P, Rcv_P2P, Receive_Reset Custom embedded firmware where the C programmer owns the framing None by default — but stray bytes may appear if Send_Config defaults are not matched

If the C programmer on the PCB side has a complete Modbus RTU implementation, use MB_MASTER with the S7-1200 as master. The PLC block hides the CRC, the 3.5-character inter-frame silence, and the slave addressing, which is exactly what a custom firmware author does not want to debug from both sides.

If the C programmer insists on a "pure RS485" model and the PCB simply reads or writes bytes from a UART without a Modbus layer, the PLC must use the raw PtP blocks. This is the path that triggered the header-byte symptom discussed below.

Master/Slave Assignment and Addressing

For a single S7-1200 controlling many PCBs, the S7-1200 must be the Modbus master. Each PCB is a slave with a unique address in the range 1-247. Address 0 is the broadcast address and is not used for doors or lights because no slave acknowledgement is returned. The PLC scans the slaves with FC 05 (Write Single Coil) for door open/close and FC 15 (Write Multiple Coils) or FC 06 (Write Single Register) for light control. Status feedback is typically FC 02 (Read Discrete Inputs).

Slave count must respect the RS485 load-unit budget. The CM 1241 driver is rated for 32 standard unit loads (UL). Modern embedded UART transceivers (MAX485, SN75176, THVD1450) are 1/8 UL or 1/16 UL, so a segment can in practice exceed 32 physical nodes; the actual limit is the bus capacitance (≤ 50 pF/foot × total length) and the available drive strength on the dominant transmitter. With 1/8 UL transceivers, 64 nodes are routinely achievable on a 600 m cable at 19200 bit/s.

TIA Portal Configuration: Port_Config and Send_Config

Insert the CM 1241 from the hardware catalog, give it a free I/O address, and open the device configuration. Set the operating mode to "RS485" (half duplex). Configure the protocol parameters to match the embedded firmware byte for byte:

Serial parameters for the PCB firmware
Parameter Typical value Notes
Baud rate 19200 bit/s Match the C firmware uart_init()
Data bits 8 Required for Modbus RTU
Parity None Two stop bits; alternative is Even + one stop bit
Stop bits 1 (with parity) or 2 (no parity) Embedded UART must match
Flow control None RS485 is implicit

If parity is set to None, the link loses one frame-error detection mechanism. This is a deliberate trade-off when the embedded side cannot be re-programmed. The compensating measure is hardware-level line discipline (termination + bias + 3.5-char inter-frame gap).

The "00 Header Byte" Symptom — Root Cause Analysis

Symptom: every time Send_PTP (or its older alias Send_P2P) transmits the buffer, the first byte on the line is 0x00, regardless of what the application wrote into the send buffer. On a Modbus-RTU bus this is catastrophic because the receiving slave sees a corrupt slave address and either ignores the frame or replies with exception 0x02 (illegal data address).

Root cause: TIA Portal's Port_Config + Send_Config pair carries a "frame end" and "idle line" timeout that, when left at the default of 12 bit-times, can interpret the UART's transmit shift-register flush as a half-character. The internal DMA then emits a fill byte (0x00) into the first transmit position, because the TX FIFO has not been pre-loaded with application data when the line is sampled as idle. The fill is hardware-level; you cannot suppress it with LEN or OFFSET alone.

The Siemens knowledge base article "How do you compensate for the string mismatch caused by the RCV_PTP and SEND_PTP blocks?" describes the byte-stripping technique on the receive side (truncating the first received byte and concatenating the remaining buffer). The transmit-side cause, however, is the configuration pair, not the receive logic, so the workaround that fixes the transmit symptom is to either remove the configuration pair entirely or to set the idle-line and break parameters to zero.

Why parity = None matters here. With parity = None, a single noise pulse or a TX-FIFO fill byte is not flagged by the UART, so the embedded receiver accepts the spurious byte as valid data. With parity = Even, the same byte almost always fails parity, and the slave rejects the frame cleanly. The cheaper, more robust fix is to align the Send_Config parameters to the bus timing — do not "solve" the problem by switching to parity.

Workaround 1 — Remove Port_Config and Send_Config

Tested and confirmed by the field integration. Drop the configuration blocks from the OB1 / cyclic OB and call Send_P2P directly. The module retains its hardware configuration from the device view, and the application writes straight into the TX FIFO.

  1. In the PLC device configuration (TIA Portal > Device View > CM 1241 > Properties > Port Configuration), set baud, parity, data, and stop bits. These become the module's hardware defaults.
  2. Do not call Port_Config from the program. Hardware defaults are already active after power-up.
  3. Do not call Send_Config. The default idle-line and break times are bypassed.
  4. Call Send_P2P directly. The LEN parameter controls exactly how many bytes are sent. A 6-byte payload produces 6 bytes on the wire with no leading 0x00.

Workaround 2 — Zero the Idle-Line and Break Times

Keep the configuration pair, but change two parameters inside Send_Config. The defaults of 12 bit-times are designed to give a 3.5-character RS485 inter-frame gap, but they are over-conservative for short-payload embedded traffic and they cause the fill-byte artifact.

  1. Keep Port_Config with the same baud, parity, and stop-bit parameters as the device view.
  2. Keep Send_Config, but set:
    • IDLELINE = 0 bit-times (was 12)
    • BREAK = 0 bit-times (was 12)
  3. Call Send_PTP with the LEN parameter set to the actual payload length (6 in the reported case).

The two parameters are mapped at the function-block input pins. A typical snippet in SCL is shown below; the equivalent ladder is one rung with MOVE blocks into the IN pins of the Send_Config instance DB.

// FB "Send_Config_DB" instance of Send_Config
// Inputs
#REQ          := TRUE;          // edge-triggered on rising edge
#PORT         := 271;           // hardware ID of CM 1241, 0x10F
#SEND_CFG.IDLELINE := 0;         // bit-times, was 12
#SEND_CFG.BREAK    := 0;         // bit-times, was 12
#SEND_CFG.FILLCHAR := 16#00;     // unused once IDLELINE=0
#DONE         => #cfgDone;
#ERROR        => #cfgErr;
#STATUS       => #cfgStatus;

// FB "Send_P2P_DB" instance of Send_P2P
#REQ          := #sendReq;
#PORT         := 271;
#BUFFER       := #txBuf;        // ARRAY[0..5] OF BYTE
#LEN          := 6;             // 6 payload bytes
#DONE         => #sendDone;
#ERROR        => #sendErr;
#STATUS       => #sendStatus;

Electrical Discipline: Termination, Bias, and Common-Mode

Even after the configuration is fixed, the symptom will reappear intermittently on long cables if the bus is not electrically disciplined. Three rules apply:

  1. Termination. Install a 120 Ω resistor between A and B at both physical ends of the segment, not at every node. A middle node must not be terminated. Termination absorbs the reflection at the end of the cable so the receiver sees a clean edge.
  2. Bias. Pull A up to +5 V through 680 Ω and B down to GND through 680 Ω at one end of the segment (typically the master). Bias forces the bus to a defined "1" state when no transmitter is active. Without bias, the line floats and the UART can interpret the noise floor as a start bit, which is a second source of stray bytes.
  3. Common-mode. The CM 1241 accepts -7 V to +12 V on the signal pair. If the PCB ground is referenced to a different earth potential (e.g. a long cable to a remote electrical room), insert an isolated RS485 repeater (e.g. Phoenix Contact PSM-ME-RS485) at the segment boundary to keep the differential voltage inside the common-mode window.

Recommended bias/termination network: 120 Ω across A-B at the master, plus the 680 Ω/680 Ω divider on the master side. At the far end, a 120 Ω across A-B. No bias at the far end — a single bias source per segment is sufficient.

Receiving the Reply: RCV_PTP / Rcv_P2P

Once the transmit side is clean, the receive side must be configured to absorb the 3.5-character inter-frame gap and deliver a complete Modbus RTU frame to the application. Use Rcv_P2P with the same hardware ID. The receive block returns a length and a buffer; the application code validates the CRC, the slave address, and the function code, then strips the response payload.

Order of block calls. Call Rcv_P2P before Send_P2P on every cycle. The receive block runs in the background, and its status must be 0 (no receive in progress) before a new transmit is issued. Otherwise the PLC raises status 16#80C8 (resource busy) and the request is dropped.

The string-mismatch workaround from the Siemens KB article (drop the first received byte and concatenate the rest) is only relevant when the embedded slave intentionally inserts a leading SOF or sync byte that the C programmer chose. For a clean Modbus-RTU slave, do not apply the workaround — the receive block already starts on the first real byte.

Verification Procedure

After the fix, verify the link with the following checks. Each step has a pass criterion.

  1. Wire-level check. Connect a USB-to-RS485 converter (FTDI FT232 or Moxa UPort 1130) to the segment at a tap point. Open a Modbus-RTU master simulator on the PC (simplymodbus.ca, modbus tools, or your own terminal). Send FC 03 to address 1, register 0. The PCB replies within 50 ms. A logic-analyzer capture of the TX line of the CM 1241 must show the exact 8 bytes the application wrote into the send buffer, with no leading 0x00.
  2. Error code check. Inspect STATUS on the Send_P2P instance DB. After a successful transmit it returns 16#0000. Persistent 16#80C8 indicates the receive block is still active; persistent 16#8185 indicates a length or buffer configuration mismatch.
  3. Loop-back test. Tie A to A and B to B on a single PCB node and run FC 08 (diagnostic, sub-function 00) from the PLC. The slave must echo the request byte for byte. This validates framing, parity (if any), and inter-frame timing without exercising application logic.
  4. Soak test. With all nodes on the segment, run a 24-hour cyclic scan at the production baud rate. The TIA Portal online watch table on the MB_MASTER / Send_P2P blocks must show zero error events.
  5. Common-mode margin. If the cable runs across buildings, disconnect the local earth and measure A and B to PE at the far end. Both must be inside -7 V to +12 V relative to the CM 1241 ground.

Diagnostic Flowchart

The following SVG is suitable for inclusion in a commissioning report or a maintenance binder.

Stray 0x00 on SEND_PTP? Check Port_Config and Send_Config in OB1 Both present? Workaround 1: delete both Workaround 2: IDLELINE=0, BREAK=0 Re-test with USB-RS485 tap Wire-level shows 6 bytes only — link OK

Alternative Architecture: When to Use MB_MASTER Instead

If the C programmer on the PCB side is open to it, switch to standard Modbus-RTU master mode and skip the raw PtP layer entirely. TIA Portal ships with MB_COMM_LOAD and MB_MASTER in the "Communication" palette. The advantages are:

  • PLC handles the 3.5-character inter-frame gap, CRC, and the 1.5-character intra-frame gap automatically.
  • No header-byte artifact, because the block reuses the legacy Modbus master driver that has been stable since S7-200.
  • Diagnostic tags MB_MASTER.NDR, MB_MASTER.ERROR, and MB_MASTER.STATUS are available in the watch table for direct read-out.
  • Multi-drop polling of up to 247 slaves is handled by a single instance per port, with a single data block driving the request queue.

The disadvantages are that the C programmer must implement a Modbus-RTU slave, and the PLC must be re-wired to issue standard FC 01, 02, 05, 06, 15, or 16 calls. For a green-field PCB this is the recommended path; the raw PtP path is the fallback for a non-cooperative firmware side.

Troubleshooting Matrix

Symptom → cause → action
Symptom Likely cause Action
Leading 0x00 on every transmit Port_Config / Send_Config defaults Apply Workaround 1 or 2 above
Random 0x00 / 0xFF in payload No termination, line floats Add 120 Ω at both ends, add 680 Ω bias
STATUS = 16#80C8 on Send_P2P Rcv_P2P still running Call Rcv_P2P first, or wait for DONE
STATUS = 16#8185 on Send_P2P LEN=0 or LEN>buffer Check LEN parameter and ARRAY bounds
Slave returns exception 02 Modbus address or FC not supported Verify PCB register map
Slave returns exception 04 CRC error on slave side Check parity, baud, common-mode
Intermittent fail at 115200 only Cable capacitance too high Reduce baud or shorten cable
All slaves seen as 0x00 at master A and B swapped Swap A/B; do not swap GND

Commissioning Checklist

  1. Confirm CM 1241 order number 6ES7241-1CH32-0XB0 and firmware version 2.0 or later.
  2. Verify 24 V supply on the module's power terminals; LED "TxD" must be off at idle.
  3. Configure RS485 (half duplex) in the device view; set the same baud / parity / data / stop bits as the PCB firmware.
  4. Install 120 Ω termination at both ends of the segment. Confirm continuity with a multimeter; A-B must read 60 Ω total with two terminators, 120 Ω with one.
  5. Install the 680 Ω / 680 Ω bias on the master side only. Measure A to GND = +2.5 V typical, B to GND = +2.5 V typical when no traffic.
  6. Build a single-node loop-back test before connecting the full segment.
  7. Apply Workaround 1 (preferred for new projects) or Workaround 2 (preferred when Send_Config is reused for other reasons).
  8. Capture one full Modbus transaction on a logic analyzer or USB-RS485 tap; verify byte count, CRC, and inter-frame gap.
  9. Document the slave register map and back up the TIA Portal project to the engineering repository.

FAQ

Why does SEND_PTP add a leading 0x00 byte to every Modbus-RTU frame?

The 0x00 is a TX-FIFO fill byte emitted by the CM 1241 driver when the Send_Config idle-line and break times are left at their 12 bit-time defaults. The DMA flushes the line with a fill character before the application buffer is loaded. Remove the Send_Config / Port_Config pair, or set IDLELINE = 0 and BREAK = 0 inside Send_Config, to eliminate it.

Can I keep parity = None on a Modbus-RTU link with a custom PCB?

Yes, but the bus loses one frame-error detection mechanism. Compensate with proper 120 Ω termination, 680 Ω bias, and a 3.5-character inter-frame gap on the master. With these measures, parity = None is acceptable for 19200 bit/s and below on a clean cable run.

Should I use Modbus RTU master blocks or raw SEND_PTP / RCV_PTP?

Use MB_COMM_LOAD and MB_MASTER when the C programmer is willing to implement a standard Modbus-RTU slave. Use Port_Config / Send_Config / Send_P2P / Rcv_P2P only when the embedded firmware cannot be changed and the PCB expects raw bytes. The raw path requires the fixes documented in this article.

What is the maximum number of PCB nodes on a single CM 1241 port?

32 standard RS485 unit loads is the datasheet limit, but modern 1/8 UL transceivers allow 64 or more physical nodes. The real limits are bus capacitance (≤ 50 pF/foot × total length) and the chosen baud rate. At 19200 bit/s with Belden 3106A cable, 64 nodes on 600 m is a typical working envelope.

How do I compensate for a string mismatch on the receive side?

Apply the workaround from Siemens KB article 42002283: drop the first received byte, then concatenate the remaining buffer in the application code. Use this only when the embedded slave intentionally emits a leading sync byte. For a clean Modbus-RTU slave, no receive-side workaround is needed.

Back to blog