S7-1200 TSEND TRCV: Resolving TCP Receive Cycle Time Failures

David Krause14 min read
SiemensTIA PortalTroubleshooting
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

S7-1200 TSEND TRCV: Resolving TCP Receive Cycle Time Failures

The Siemens SIMATIC S7-1200 (CPU 1214FC, firmware V4.x) open user communication blocks TSEND, TRCV, and TCON frequently exhibit intermittent data loss when the receive polling interval is shorter than the OB1 cycle time of the user program. This article documents a field-verified remediation for a 100-byte TCP payload polled at 25 ms from a third-party controller (Lenze C300) into an S7-1200, with an OB1 scan of 23 ms, and explains why edge-triggering the REQ input combined with a cyclic interrupt OB eliminates the symptom without changing the physical transport.

Field Symptom Summary
• Send direction (S7-1200 → Lenze, 100 bytes / 10 ms via TSEND): stable, no loss.
• Receive direction (Lenze → S7-1200, 100 bytes / 25 ms via TRCV): intermittent, partial payloads, STATUS word returns transient error codes.
• Reducing Lenze transmit interval to 100 ms: stable but unacceptable for the motion loop.
• OB1 maximum cycle time: 23 ms (monitored via _OB1_CYCL in the watch table).

1. Problem Description

A SIMATIC S7-1200 CPU 1214FC (article number 6ES7214-1AF40-0XB0 or later variant) exchanges 100 bytes per direction with a Lenze C300 inverter/controller over PROFINET/Industrial Ethernet using the standard TCP transport from the SIMATIC open user communication library. TSEND is pulsed at 10 ms from OB1 with no observed loss. TRCV is configured with the REQ input permanently TRUE in the same OB1 pass. The Lenze controller transmits a new 100-byte frame every 25 ms. The following conditions are observed:

  • Frame loss rates of 5–15 % during steady-state operation, depending on background process load.
  • Status word STATUS of TRCV intermittently returns W#16#80C9 (connection resource in use / resource temporarily unavailable) and W#16#8180 (connection not yet established / handshake error).
  • Increasing the Lenze transmit interval to 100 ms eliminates loss but violates the 10 ms motion-update requirement.
  • No PROFINET diagnostic alarms are raised; the physical link (link LED, port statistics) remains fault-free.

The user's hardware and configuration layout is summarized below.

Parameter Value
PLC SIMATIC S7-1200, CPU 1214FC (DC/DC/DC or AC/DC/RLY)
Firmware V4.4 or later (T-CON block library V3.x or V4.x)
Counterpart Lenze C300 controller (Ethernet/IP/TCP socket server)
Transport TCP (RFC 793), IPv4, port 502 / custom
Payload per frame 100 bytes (8192 byte maximum per SIMATIC block)
Send interval (S7) 10 ms (OB1-driven)
Receive interval (Lenze) 25 ms
OB1 maximum cycle 23 ms
Blocks used TCON, TSEND, TRCV, TDISCON

2. Root Cause Analysis

Two distinct mechanisms cause the receive-side failures described above. Both are well documented in the SIMATIC S7-1200 programmable controller system manual and the Open User Communication programming manual.

2.1 REQ Edge-Trigger Behavior of TRCV

The TRCV block (FB 84 in the standard library, also referenced as "TRCV" in TIA Portal V13+) uses an edge-triggered interpretation of the REQ input when the connection is configured with ADHOC = FALSE (i.e., when a length header is expected) and a level-triggered interpretation only when ADHOC = TRUE. For the 25 ms polling case described here, ADHOC is typically FALSE (Lenze C300 transmits a fixed 100-byte frame with no SIMATIC length header). With the REQ input tied permanently TRUE inside OB1, the block attempts to start a new receive job on every cycle. Two effects appear:

  • The block re-arms the receive job before the previous job's DONE bit is observed, causing STATUS transitions that are not user-visible because the program never reaches the next network where DONE/NDR would be evaluated.
  • If the OB1 cycle (23 ms) is shorter than the Lenze transmit interval (25 ms) and roughly aligned with it, multiple consecutive OB1 passes see no incoming data, while a single pass occasionally races with a TCP segment arrival. The receive is completed on a random scan, and the STATUS word can latch transient connection-resource errors.

The Siemens open user communication reference is explicit on this: TSEND, TRCV, TCON, and TDISCON detect a rising edge on REQ internally. If REQ is held at TRUE across multiple OB1 scans, the block does not see a new edge and will not retrigger reliably; furthermore, in some firmware versions the block re-enters while the internal job state machine is still in a transitional state, surfacing as 80C9/8180.

2.2 OB1 Scan vs. Interrupt OB Priority

The S7-1200 executes all user program levels under a single priority class by default. OB1 is the cyclic task with priority 1 (lowest). Any code inserted into OB1 shares CPU bandwidth with the entire machine program. If OB1 takes 23 ms, only ~43 scans per second are possible. Trying to poll a 25 ms remote transmit from a 23 ms scan introduces phase alignment that is statistically guaranteed to produce at least one missed window per second, especially when system events (PROFINET IO update, web server, HMI polling, time-of-day synchronization) extend OB1 past 23 ms.

The correct mechanism for time-deterministic I/O exchange is a cyclic interrupt OB (OB30–OB38 on S7-1200). The hardware timer that drives a cyclic interrupt is independent of OB1 and will pre-empt OB1 when its phase elapses. This decouples the TCP poll rate from the OB1 maximum cycle and ensures the REQ edge is generated at a known, repeating interval.

3. Solution: Edge-Triggered REQ with Cyclic Interrupt

The combined fix is twofold: (a) drive the REQ input of TRCV (and TSEND) with a pulse that is high for exactly one OB scan, then low for at least one OB scan; and (b) execute the TCP exchange inside a cyclic interrupt OB rather than OB1.

3.1 Edge Generation Pattern

A robust pattern is to maintain a BOOL edge tag, e.g., "tcpTick", that is set TRUE inside the cyclic interrupt OB on the first call after a new interval starts, and reset by the same OB on the next call. The pattern below works for both TSEND and TRCV:

// In OB30 (10 ms cyclic interrupt)
IF "tcpTick" = FALSE THEN
    "tcpTick" := TRUE;
    "sendReq" := TRUE;   // pulse TSEND REQ
    "recvReq" := TRUE;   // pulse TRCV REQ
ELSE
    "sendReq" := FALSE;
    "recvReq" := FALSE;
END_IF;

The next OB30 invocation flips the tags back to FALSE, producing a clean one-cycle pulse that the open user communication blocks interpret as a rising edge.

3.2 Why a Cyclic Interrupt OB

Attribute OB1 (cyclic) Cyclic Interrupt (OB30–OB38)
Phase source End-of-previous-OB1 self-retrigger Hardware timer (configurable 1–60,000 ms)
Jitter High; scales with program length Sub-millisecond on S7-1200
Pre-emption Cannot pre-empt itself Pre-empts OB1; can be pre-empted by higher-priority OB
Determinism for 25 ms poll Marginal at 23 ms scan Excellent at 25 ms OB30 phase
Worst-case latency Unbounded (OB1 overrun watchdog) One phase minus OB30 execution time

Configure OB30 with a phase of 10 ms (matching the S7-1200 send rate) to start. The receive can then be polled at any rate the block supports; for the Lenze 25 ms transmitter, set OB30 to 25 ms or run TRCV only every second or third OB30 invocation using a counter.

4. Protocol Selection: TCP vs UDP vs ISO-on-TCP

If the edge-trigger + cyclic interrupt fix is insufficient — for example, if the application requires lossless, high-rate exchange where every missed poll is a hard fault — consider switching the transport. The three options supported by S7-1200 open user communication are summarized below.

Property TCP UDP ISO-on-TCP (RFC 1006)
Connection-oriented Yes (3-way handshake) No (datagram) Yes (TPKT/Wrapping)
Block size Up to 8192 bytes Up to 8192 bytes (1472 max practical) Up to 8192 bytes
Acknowledgment Yes (transport layer) No (application layer) Yes (transport layer)
S7-1200 support All firmware V4.x All firmware V4.x Firmware V4.x with TCON connection DB
Header overhead ~20 bytes IP + 20 TCP ~20 bytes IP + 8 UDP ~20 bytes IP + 4 TPKT
Determinism on S7-1200 Good with cyclic OB Excellent (no ACK round-trip) Good with cyclic OB
Lenze C300 compatibility Verified by user Typically yes (check firmware) Lenze support varies by firmware

UDP is documented in the Siemens entry ID 20983558 as implemented for performance reasons. Because UDP has no transport-layer acknowledgment, the application must tolerate packet loss or implement its own sequence counter. ISO-on-TCP is described in the SIMATIC S7-1200 manual collection as "an efficient communications protocol closely tied to the hardware, suitable for medium-sized to large data amounts (up to 8192 bytes)" and is recommended when the partner supports RFC 1006 framing.

If the Lenze C300 firmware version does not publish ISO-on-TCP or UDP, TCP with edge-triggered REQ inside a cyclic interrupt OB remains the lowest-risk option. UDP should be reserved for scenarios where the motion controller can tolerate one missed sample per N samples.

5. TCON Connection Configuration

Regardless of which transport is selected, the TCON connection DB must be parameterized correctly. The minimum required fields are shown below for the TCP case.

Field (DB) Value (TCP to Lenze C300)
InterfaceId 64 (decimal) — built-in PROFINET interface of CPU 1214FC
ID 1 (arbitrary, must be unique on the CPU)
ConnectionType 16#0B (TCP/IP, B#16#0B per TIA Portal dropdown)
ActiveEstablished TRUE (S7-1200 opens the socket to Lenze)
RemoteAddress Lenze C300 IP, e.g., 192.168.10.20
RemotePort Lenze listening port, e.g., 502 or vendor-defined
LocalPort 0 (let the stack assign an ephemeral port)
LocalAddress S7-1200 IP, e.g., 192.168.10.10

For ISO-on-TCP, replace ConnectionType with B#16#12 and add TSAP fields. For UDP, use B#16#13. Note that on S7-1200 firmware V4.x the open user communication block library is version-locked; mismatching the library version against the firmware is itself a common source of STATUS 8180 at startup.

6. Step-by-Step Implementation

  1. Add a cyclic interrupt OB. In TIA Portal project tree, right-click "Program blocks → Add new block → Organization block → Cyclic interrupt". Select OB30 (priority 16 on S7-1200 by default). Set the phase time to 25 ms to match the Lenze transmit interval. Click OK.
  2. Move the TCP exchange code from OB1 to OB30. Cut the TCON, TSEND, and TRCV instance calls and paste them into OB30. Keep TCON called once with edge-triggered REQ for the connection-establish phase, then call TSEND and TRCV on every subsequent OB30 invocation.
  3. Implement the edge tag. Add a static BOOL tag "tcpTick" in the same FB that owns the instances, or in a global DB. Use the pattern from section 3.1 to drive REQ on TSEND and TRCV for exactly one OB30 pass.
  4. Add status monitoring. In OB30, latch TSEND_DONE, TSEND_ERROR, TRCV_NDR, TRCV_ERROR, STATUS, and RCVD_LEN into a watch-table DB so the engineering tool can graph frame loss.
  5. Configure TCON parameters. Open the connection DB and verify all fields in section 5. Compile and download.
  6. Compile and download. Mark "Software (all)" → Download to device. Use "Extended download with reset" only after recording the current program; alternatively, perform a STOP → RUN cycle to re-establish the TCP socket.
  7. Verify online. Open the watch table and confirm that TRCV_NDR pulses every ~25 ms with RCVD_LEN = 100 and STATUS = 0.

7. Verification

Use the following checks after the fix is in place. Each one targets a different failure mode that the original symptom could mask.

Check Tool / Tag Expected Result
OB30 phase time Online & Diagnostics → Cycle time ~25 ms ± 0.5 ms
OB1 cycle time _OB1_CYCL_PREV, _OB1_CYCL_MAX Remains at original ~23 ms; not extended by TCP code
TSEND success rate Counter incrementing on TSEND_DONE 100 % over 60 s
TRCV success rate Counter incrementing on TRCV_NDR ≥ 99 % over 60 s at 25 ms cadence
STATUS word Watch table W#16#0000 on every NDR; no 80C9, 8180, 8181, 80A1
Connection status TCON output STATUS / TCON_BUSY Busy = FALSE, DONE = TRUE after first connect
PROFINET port counters Online & Diagnostics → Statistics → Port No discards, no CRC errors, sent = sent segments matching remote ACK

7.1 Error Code Reference

The most relevant STATUS values for the open user communication blocks on S7-1200 are listed below. Always cross-reference the STATUS value against the corresponding FB documentation in TIA Portal; values may change between firmware versions.

STATUS (hex) Block Meaning Remediation
W#16#0000 TRCV/TSEND No error None
W#16#7000 TRCV/TSEND No job active Normal after DONE/ERROR pulse
W#16#7001 TRCV/TSEND Job started, BUSY = TRUE Continue calling block
W#16#7002 TRCV/TSEND Job accepted, executing Continue calling block
W#16#80C9 TRCV Resource temporarily unavailable / overlapping job Pulse REQ; do not hold TRUE; move to cyclic OB
W#16#8180 TRCV/TSEND Connection not established Verify TCON parameters; check physical link
W#16#8181 TRCV/TSEND Connection lost during job Verify partner; check cable/port LED
W#16#80A1 TRCV/TSEND Connection terminated by partner Partner closed socket; re-run TCON
W#16#80B0 TRCV ADHOC mode requires LEN = 0 Set LEN = 0 for ADHOC
W#16#80B1 TRCV ADHOC = FALSE but LEN = 0 Set LEN = expected length
W#16#8085 TRCV/TSEND Wrong LEN parameter or pointer Re-check ANY pointer variant

8. Cycle Time Optimization

If after the OB30 fix the OB1 maximum cycle time still exceeds 25 ms — for example, because HMI tags are being read each scan — the application is fundamentally throughput-bound. Three mitigations are appropriate, in order of impact:

  1. Move all time-deterministic I/O to dedicated cyclic interrupt OBs. OB30 at 25 ms for TCP receive, OB31 at 10 ms for TCP send, OB32 at 5 ms for fast analog sampling. Each OB has its own priority and cannot be blocked by the others.
  2. Reduce OB1 footprint. Strip string processing, arithmetic-heavy diagnostics, and any HMI-triggered computations out of OB1. Move them to OB35 (100 ms) or a time-of-day OB.
  3. Tune PROFINET IO update. If PROFINET devices are configured with a 1 ms send clock, the CPU's PROFINET base cycle is 1 ms and contributes a fixed overhead per OB1 scan. Increasing the send clock to 2 ms halves the PROFINET-related OB1 increment.
Watchdog interaction. The S7-1200 cycle monitoring time defaults to 150 ms. If OB1 exceeds the configured maximum cycle, the CPU goes to STOP. This is unaffected by the cyclic interrupt fix; if OB1 extension is the actual cause of the failure rather than TCP timing, the CPU will log a corresponding diagnostic buffer entry with text "Cycle time exceeded". Always check the diagnostic buffer first when STOP events coincide with TCP loss.

9. When to Consider UDP Instead

If, after applying the edge-trigger + cyclic interrupt fix, the application still loses more than one frame per ten seconds, evaluate UDP. The tradeoff matrix below clarifies the design decision.

Decision Criterion Keep TCP Switch to UDP
Frame loss tolerance Zero Up to a few % acceptable
Partner supports UDP N/A Required (Lenze C300 ≥ specific firmware)
Maximum payload per datagram 8192 1472 (Ethernet MTU minus IP/UDP headers)
Sequencing Implicit (TCP byte stream) Application must add sequence counter
Implementation complexity Lower (block-level) Higher (custom error handling)

The Siemens support entry 20983558 explicitly notes that the unacknowledged nature of UDP has "unfavorable consequences" — meaning the application must accept loss or compensate for it. For the Lenze C300 in this user's case, a 100-byte payload fits well within the UDP MTU; a sequence number in the first byte (0..255 rolling) is sufficient to discard duplicate or out-of-order datagrams at the S7-1200.

10. Field-Proven Checklist

  1. OB30 created with phase = 25 ms (or 10 ms if faster than the partner).
  2. TCP exchange code moved from OB1 to OB30.
  3. Edge tag tcpTick implemented; REQ is a one-OB30 pulse, not a level.
  4. TCON connection DB populated per section 5; STATUS returns 0 after first connect.
  5. RCVD_LEN = 100 on every TRCV_NDR.
  6. No STATUS 80C9, 8180, 8181, or 80A1 in any 60 s window.
  7. PROFINET port statistics show no discards or CRC errors.
  8. OB1 cycle time unaffected by TCP code; _OB1_CYCL_MAX unchanged.
  9. If loss persists >1 frame/10 s, evaluate UDP with sequence numbering.

Why does TRCV lose data when REQ is held TRUE in OB1?

The TRCV block interprets REQ as a rising edge for non-ADHOC connections. Holding REQ permanently TRUE either retriggers the block before the internal state machine returns to idle (STATUS 80C9) or, more commonly, races the TCP receive against the OB1 scan, producing intermittent NDR/STATUS transitions that the program cannot resolve in time. Pulse REQ for exactly one OB scan to guarantee the block sees a clean edge.

Should I run TSEND and TRCV from OB1 or a cyclic interrupt OB?

For deterministic rates faster than OB1 can scan, use a cyclic interrupt OB (OB30–OB38). OB30 at a 10 ms phase is a stable match for the 10 ms S7-1200 → Lenze send requirement and at 25 ms for the Lenze → S7-1200 receive requirement. OB1 is acceptable only if its maximum cycle is comfortably below the polling interval (rule of thumb: at least 4:1 ratio).

What does STATUS 80C9 mean on TRCV?

STATUS W#16#80C9 indicates a transient resource conflict inside the open user communication stack — typically that the block was called while a previous job had not completed, or that REQ was pulsed too rapidly for the stack to schedule. Pulsing REQ once per cyclic interrupt OB scan and verifying OB1 is not preempting the TCP code resolve this in nearly every field case.

Can I use UDP instead of TCP for the Lenze C300?

Yes, if the Lenze C300 firmware exposes a UDP socket server for the same data block. UDP removes the transport-layer acknowledgment round-trip, lowering jitter at the cost of accepting that datagrams may be dropped or reordered. Add a 1-byte sequence counter in the application payload so the S7-1200 can discard duplicates. Siemens documents UDP open user communication in entry 20983558.

What is the maximum payload per TSEND/TRCV call on S7-1200?

Up to 8192 bytes per call, provided the receiving connection is configured with sufficient buffer. For UDP, the practical Ethernet MTU limit is 1472 bytes per datagram. The SIMATIC S7-1200 manual collection describes ISO-on-TCP as suitable for "medium-sized to large data amounts (up to 8192 bytes)" using TPKT framing.

Back to blog