Siemens S7-1200 RCV_PTP Buffer Shift on CM1241 RS232: Fix

David Krause13 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

Siemens S7-1200 RCV_PTP Buffer Shift on CM1241 RS232: Troubleshooting Continuous Reception

Problem Overview

A Siemens S7-1200 CPU 1211C DC/DC/Rly (firmware V4.x class, paired with a CM 1241 RS232 communication module, order number 6ES7241-1AH32-0XB0) is configured in TIA Portal V15 to read weight data from a serial scale. The link is 3-wire: RX, TX, GND, no hardware handshaking. When the scale transmits on demand (operator pressing the print button on the device), the data arrives intact in the receive DB. When the scale transmits continuously at a fixed cadence, the buffer appears to shift by one byte per transmission:
Observed buffer behavior with continuous transmission
Index 1st reception 2nd reception 3rd reception (typical)
dati[0] '+' (0x2B) '1' (0x31) '2' (0x32)
dati[1] '1' (0x31) '2' (0x32) '3' (0x33)
dati[2] '2' (0x32) '3' (0x33) '.' (0x2E)
... ... ... ...
dati[13] '3' (0x33) '$' (0x24 or end sentinel) '+' (0x2B)
dati[14] '$R' (0x0D, CR) '$L' (0x0A, LF) '1' (0x31)
dati[15] '$L' (0x0A, LF) '+' (0x2B) '2' (0x32)
The original LAD/FBD logic uses a permissive pattern: as soon as the LENGTH output returns to 0, the program sets EN_R back to TRUE and re-arms the receiver. Under continuous transmission, the second frame is captured while the trailing bytes of the first frame are still in the S7-1200 PtP FIFO, so the firmware concatenates them and the user sees a one-position logical shift. This is not a hardware defect; it is a configuration/sequencing issue.
Symptom summary: Buffer contents appear shifted left by one byte per reception, the LENGTH output occasionally reports 0 mid-frame, and the start-of-frame character ('+', 0x2B) appears at the wrong index in the buffer. NDR toggles faster than the actual frame cadence, indicating the receiver is being re-armed before the previous frame has fully drained from the FIFO.

Root Cause Analysis

The CM 1241 RS232 PtP interface uses an internal hardware FIFO of up to 1024 bytes per port. According to the official Siemens documentation, "Each PtP communication interface can buffer up to a maximum of 1024 bytes. This could be one large message or several smaller messages." (see RCV_PTP (Enable receive messages) – SIMATIC S7-1200 Manual Collection). The RCV_PTP instruction copies whatever bytes are available in the FIFO at the moment the message is considered complete. A message is declared complete when one of the configured end conditions is met:
  1. An end delimiter (1 or 2 characters) is received.
  2. The intercharacter timeout elapses with no new bytes.
  3. The message timeout (overall frame time) elapses.
  4. The 1024-byte FIFO capacity is exceeded.
When no start delimiter is configured and the end delimiter is multi-character (CR+LF), the firmware relies on detecting the delimiter at the end of the FIFO. If the user re-arms the receiver immediately after NDR rises, the next frame is captured before the delimiter of the previous frame has been processed and the FIFO pointer is off by one byte. Three contributing factors were present in the original program:
  1. No start delimiter was defined in the CM 1241 port configuration. The '+' character (0x2B) is present in the data stream but is not used as a synchronization anchor.
  2. Intercharacter timeout was left at default or set too short, so a brief gap between frames (e.g., the scale's internal pause) is interpreted as the end of the message.
  3. Re-arming logic used IF "Tag_10" = 0 THEN "Tag_1" := 1; END_IF; which sets EN_R to 1 the same OB1 cycle the LENGTH output goes to 0. Under heavy load or slow OB1, this allows a new frame to begin before the previous one is fully drained.

Solution 1 – Configure a Start Delimiter and End Delimiter

Open the CM 1241 RS232 device configuration in TIA Portal and configure the message framing so the firmware has explicit, deterministic start and end markers.
  1. Open Devices & Networks, select the CM 1241 RS232 module.
  2. Navigate to Properties > Port configuration.
  3. Set the active transmission parameters: baud rate, parity, data bits, stop bits to match the scale (commonly 9600, 8, N, 1 for industrial scales).
  4. Navigate to Properties > Message configuration.
  5. Set Start delimiter to Use start delimiter and enter the hex value 2B (the ASCII '+' character).
  6. Set End delimiter to Use end delimiter and enter the two hex values 0D 0A (CR LF).
With the start delimiter defined, the CM 1241 discards any bytes received before the 0x2B and aligns every reception on a clean boundary. The reference for the delimiters is given in the official TIA Portal help for the S7-1200 PtP instructions (see RCV_PTP: Enable receive messages (S7-1200) – STEP 7 V21 documentation).
Recommended message configuration for the scale scenario
Parameter Value Meaning
Start delimiter 0x2B ASCII '+' synchronizes the start of every frame
End delimiter 1 0x0D Carriage return terminates the frame
End delimiter 2 0x0A Line feed (optional, can be disabled if scale sends only CR)
Intercharacter timeout 20 ms Max gap between two bytes within one frame
Message timeout Disabled or 200 ms Used as a backstop, not as primary trigger
FIFO buffer size 1024 bytes (default) Internal hardware FIFO

Solution 2 – Tune the Intercharacter Timeout

The intercharacter timeout is the correct parameter to use for a polled, framed protocol such as a scale that emits a fixed-length record. The message timeout should not be the primary end condition for short frames. The intercharacter timeout must be:
  • Longer than the longest legal intra-frame gap. For a 16-byte frame at 9600 baud, the byte time is approximately 1.04 ms, so a value of 10–20 ms is safe.
  • Shorter than the inter-frame gap the scale produces between consecutive transmissions. If the scale sends a frame every 250 ms, set the intercharacter timeout to roughly 50 ms.

Solution 3 – Correct the Re-Arming Logic in the PLC

The original logic re-enables the receiver as soon as LENGTH is 0. This is unsafe under continuous transmission. Replace the permissive pattern with a deterministic state machine that only re-arms after the previous frame has been completely consumed by the application.

Recommended SCL implementation:

// State machine for RCV_PTP control
IF "RCV_PTP_DB".ERROR THEN
    // Capture and clear error
    "LastError" := "RCV_PTP_DB".STATUS;
    "RCV_PTP_DB".EN_R := FALSE;
    "Tag_1" := 0;
    "Tag_4" := 1;  // Error flag for HMI
END_IF;

IF "Tag_1" = 0 AND NOT "RCV_PTP_DB".ERROR THEN
    // Receiver idle: arm it
    "RCV_PTP_DB".EN_R := TRUE;
    "Tag_1" := 1;
END_IF;

"RCV_PTP_DB"(PORT := 16#10D,
              BUFFER := "DB232".dati,
              NDR => "Tag_2",
              ERROR => "Tag_3",
              STATUS => "Tag_9",
              LENGTH => "Tag_10");

IF "Tag_2" THEN
    // New data complete: copy to working buffer, do NOT re-arm yet
    "FrameReady" := TRUE;
    "LastLength" := "Tag_10";
    "RCV_PTP_DB".EN_R := FALSE;
    "Tag_1" := 0;
END_IF;

// Process frame on a slower task or in a separate FB
IF "FrameReady" THEN
    // Parse "DB232".dati[0..LastLength-1] and convert ASCII to weight
    // ...
    "FrameReady" := FALSE;
END_IF;

The key change is to drop EN_R to FALSE the cycle NDR becomes TRUE, process the data, then re-arm on the next OB1 pass. This guarantees one frame per NDR edge and prevents the firmware from concatenating consecutive transmissions.

OB1 priority: If the user program runs in OB1 (main cyclic task), place the RCV_PTP call at the very beginning of OB1 and the parsing logic in a separate FC or FB called at the end. This minimizes the time between NDR and EN_R := FALSE, which is the window during which overlapping frames can occur.

Solution 4 – Reset the Receive DB Between Frames

If the application requires a clean buffer for every reception, initialize the receive DB to a known pattern (e.g., 16#20 space or 16#00) immediately after copying the data:
// After processing, clear the receive area
FOR i := 0 TO 31 DO
    "DB232".dati[i] := 16#00;
END_FOR;
"Tag_10" := 0;
This makes any residual data immediately visible during HMI diagnostics and prevents stale bytes from being mistaken for valid payload.

Verification Steps

After applying the three solutions above, validate the behavior in this order:
  1. Download the new hardware configuration (with start/end delimiter) and the new program to the CPU. Perform a STOP-to-RUN transition.
  2. Put the scale in continuous transmission mode at its maximum cadence (typically 10 Hz for industrial scales).
  3. Open the Watch table in TIA Portal online view and monitor DB232.dati[0] through DB232.dati[15], plus the NDR, ERROR, STATUS, and LENGTH tags.
  4. Confirm that dati[0] is always 16#2B ('+') on every NDR rising edge.
  5. Confirm that dati[14..15] are always 16#0D 16#0A on every NDR rising edge.
  6. Confirm that LENGTH toggles between 16 and 0 only, never in between.
  7. Confirm that ERROR remains 0 and STATUS remains 16#0000 for a minimum of 5 minutes of continuous operation.
  8. Disconnect the scale, send a known test pattern from a serial terminal (e.g., +0123.45kg\r\n), and verify the PLC parses the same string.

Extended Diagnostics

If the buffer still shifts after applying the three solutions, escalate with the following diagnostics.

Status Code Cross-Reference

Common RCV_PTP STATUS values for the S7-1200 / CM 1241
STATUS (hex) Meaning Corrective action
16#0000 No error None
16#8080 Character parity error Verify parity setting matches the scale (commonly None)
16#8081 Character framing error Verify stop bits (commonly 1) and baud rate
16#8082 Overflow of receive buffer FIFO exceeded 1024 bytes; increase interframe gap or scale back data rate
16#8085 Negative acknowledgement during initialization Power-cycle the CM 1241 module
16#80A0 Buffer pointer invalid Verify the BUFFER parameter points to a valid DB of sufficient length (≥ expected max frame size)
16#80A1 FIFO overflow in CM Lower the inter-frame cadence or shorten the frame

Timing Calculation

For 9600 8N1, the per-byte transmission time is:
t_byte = (1 start + 8 data + 0 parity + 1 stop) / 9600
       = 10 / 9600
       = 1.0417 ms
A 16-byte frame is therefore approximately 16.67 ms of pure transmission time. The intercharacter timeout should be set to at least 3 × t_byte = 3.13 ms to absorb jitter, but less than the inter-frame gap. For 10 Hz continuous transmission, the inter-frame gap is 100 ms – 16.67 ms ≈ 83.33 ms, so a timeout of 20–50 ms is conservative.

Cable and Electrical Checks

  • Confirm the cable is shielded and the shield is grounded at one end (typically the PLC end).
  • Keep the cable length below 15 m for RS-232 at 9600 baud in noisy industrial environments. The CM 1241 RS232 module conforms to EIA-RS-232C; practical length in factory conditions rarely exceeds 15 m.
  • If the scale is on a different power source, verify that the grounds of the scale and the PLC are at the same potential (or use an opto-isolated RS-232 repeater).
  • Disable hardware flow control in the CM 1241 port configuration if the scale does not drive RTS/CTS (the cable in this scenario has only RX/TX/GND).

Firmware and Compatibility Notes

The user's CPU 1211C with firmware V2.0 belongs to the original S7-1200 hardware generation. The RCV_PTP behavior described above has been consistent across the V2.x, V3.x, and V4.x firmware families. With firmware V4.0 and later, the default FIFO size remained 1024 bytes, and the same start/end delimiter configuration is available. When upgrading the TIA Portal project to V16, V17, or V18, the legacy "PtP" instructions continue to work; users may also migrate to the newer USS/Modbus or free-port instruction set, but the underlying RCV_PTP semantics are unchanged. Always re-validate with the verification steps above after a TIA Portal upgrade, because the device configuration can be silently reset during a project migration.

Alternative: Use S7-1200 Freeport with a Parsing FB

If the scale protocol cannot be expressed purely as start delimiter + end delimiter + fixed frame, build a more flexible receiver using the universal freeport instruction set. The pattern is:
  1. Configure the CM 1241 with a large intercharacter timeout (e.g., 100 ms) and no end delimiter.
  2. In the PLC, accumulate bytes in a FIFO-implemented array (a shift register in a global DB).
  3. Scan the array for the 0x0D 0x0A sequence; when found, mark the frame complete and parse it.
This approach is more code-intensive but handles variable-length records, mixed protocols, and corrupted start-of-frame bytes that the strict delimiter approach would discard. It is documented in the same Siemens reference page: RCV_PTP (Enable receive messages).

Troubleshooting Matrix

Symptom-to-cause map for RCV_PTP buffer problems on the S7-1200
Symptom Likely cause First action
Buffer shifts by one byte per reception No start delimiter, EN_R re-armed before FIFO drained Define 0x2B as start delimiter, add EN_R := FALSE on NDR
dati[0] sometimes empty, sometimes correct Intercharacter timeout too short, partial frames accepted Increase intercharacter timeout to 3–5× t_byte
STATUS = 16#80A0 on first call BUFFER points to a tag that is not a true DB byte array Define a DB of type ARRAY[0..n] OF BYTE and pass it directly
STATUS = 16#8082 on heavy load FIFO overflowed because user program is too slow Move RCV_PTP to a fast OB or reduce scale cadence
Buffer always zero despite scale transmitting Wrong PORT identifier (PORT = 16#10D is for one specific CM slot; check yours) Verify the port ID in the device configuration; common values are 16#100–16#10F
Works in manual mode, fails in continuous mode Inter-frame gap in manual mode is long enough to trigger timeout; continuous mode gap is shorter than timeout but longer than intercharacter gap Tune intercharacter timeout; enable start delimiter

Field Commissioning Checklist

Use this checklist on site after the PLC program is updated:
  • ☐ Port configuration in TIA Portal matches the scale: baud, parity, data bits, stop bits.
  • ☐ Start delimiter enabled: 0x2B.
  • ☐ End delimiter enabled: 0x0D 0x0A (or 0x0D only if the scale does not send LF).
  • ☐ Intercharacter timeout set to 3–5× byte time.
  • ☐ Message timeout disabled or set well above the longest legal frame time.
  • ☐ EN_R is set to FALSE on every NDR rising edge, then re-armed on a later cycle.
  • ☐ Receive DB is large enough (≥ expected frame size + 4 bytes headroom).
  • ☐ Watch table confirms dati[0] is always 0x2B and the LENGTH output is always equal to the expected frame length (e.g., 16).
  • ☐ ERROR = 0 and STATUS = 16#0000 over a 5-minute continuous run.
  • ☐ HMI displays the correct weight value with no jitter or off-by-one digits.

Frequently Asked Questions

Why does the RCV_PTP buffer shift by one byte only in continuous mode, not manual mode?

Manual transmissions have a long inter-frame gap (the operator pressing the button), which is much greater than the intercharacter timeout, so the firmware cleanly ends each frame. Continuous transmissions have a shorter, fixed gap, so the previous frame's end delimiter (CR LF) may not have been fully processed by the firmware before the next frame's start byte arrives. Defining a start delimiter (0x2B) and explicitly toggling EN_R around NDR solves this.

What PORT identifier should I use for the CM 1241 RS232 in slot 1 of an S7-1200 CPU?

The PORT identifier is an arbitrary HW ID assigned by TIA Portal at project compile time, not the slot number. The value 16#10D shown in the original code is one valid identifier for a CM 1241 in slot 1 of certain CPU types, but you must verify it by opening the device properties of the CM 1241 and reading the "Hardware identifier" field, then converting decimal to hex. Using the wrong PORT identifier causes the call to return STATUS = 16#80A0 or similar.

Can I use a single character (only CR) as the end delimiter, or must it be two characters?

The CM 1241 supports one or two end delimiter characters. If the scale emits only CR (0x0D) and not LF, leave the second end delimiter field blank. If the scale emits CR LF, set both. The maximum end-delimiter length is two bytes, after which the firmware automatically treats the message as complete and copies it to the BUFFER.

Is the 1024-byte FIFO shared between RCV_PTP and SEND_PTP on the same CM 1241?

No, the receive FIFO (1024 bytes) and the transmit buffer (also 1024 bytes on most CM 1241 variants) are separate. You can transmit and receive simultaneously on the same port without one blocking the other. The relevant documentation note is found in the SIMATIC S7-1200 Manual Collection – RCV_PTP page.

How do I migrate this program to a CPU 1211C with firmware V4.x and TIA Portal V16/V17?

The legacy RCV_PTP instruction is fully supported on firmware V4.x and TIA Portal V16, V17, and V18. After upgrading the project, re-check the device configuration of the CM 1241 RS232 because TIA Portal may have reset the start/end delimiter settings during migration. Run the verification steps above before placing the system into production.

Back to blog