S7-1200 TCP Output Trigger: Fix Latch and Bit-Overlap Faults

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

1. Problem Summary

When two SIMATIC S7-1200 CPUs are networked over their integrated PROFINET (Industrial Ethernet) interfaces and an engineer attempts to mirror a single physical input on PLC 1 — for example, I0.0 — to a single physical output on PLC 2 — for example, Q0.0 — using Open User Communication (OUC) over TCP, three closely related symptoms consistently appear in field installations:

  • Output latches ON: Q0.0 on PLC 2 energises the moment I0.0 on PLC 1 is made TRUE, but it does not de-energise when I0.0 is returned to FALSE.
  • Random outputs trigger: Additional outputs on PLC 2 (Q0.4, Q0.6, or the entire Q0.0–Q0.7 byte) energise in seemingly random patterns, even though the application program only references I0.0 and Q0.0.
  • Persistence across power-cycle: The latched state persists after a power cycle of the receive PLC if the send PLC retains the same non-zero buffered data in the DB and re-establishes the connection with the same payload.

These symptoms are not indicative of a TCP transport fault, a Siemens firmware bug, or a defective TSEND_C / TRCV_C instruction. They are the visible signature of an application-layer data-refresh defect: the sending PLC writes a non-zero byte pattern into the send buffer one time, that byte pattern is transported intact, and the receiving PLC writes the same non-zero byte pattern to its process output image — including every bit that happens to be logic '1'.

2. Root Cause Analysis

Open User Communication on the S7-1200 transports whatever byte pattern is currently resident in the configured send data block at the moment the TSEND_C block is triggered with REQ = TRUE. The TCP stack (RFC 793, IETF STD 7) provides an ordered, lossless byte stream, but it performs no semantic interpretation of the payload. The CPU user program on the receive side ultimately moves that payload to QB0, and the cycle-end output image update (OB1 process image) applies each bit to the corresponding physical output terminal on the signal module.

Three logical mistakes, applied individually or in combination, produce the reported fault pattern:

  1. Edge-triggered buffer write with set/reset coils. A common but incorrect approach is to set individual bits in the send DB with S (Set) and R (Reset) coils on I0.0 edges. Because the S/R coils latch in the bit memory, once a bit is set it remains set until an R coil is executed. If the application program never re-evaluates the input — for example because it sits inside a one-shot that fired only on the rising edge — the bit in the buffer stays at '1' even after the physical input returns to '0'.
  2. Single-bit copy without clearing the parent byte. A second approach copies only the single bit of interest (e.g., DB_iSend.DBX0.0 := I0.0; in Structured Text, or a single contact/coil in Ladder). The other seven bits in the source byte retain their previous values. If the engineer has not initialised the remaining bits of the byte to '0' in the DB declaration or in startup OB100, the residual pattern is transmitted to the receiver and applied to the corresponding outputs.
  3. Missing continuous refresh. The send DB is loaded only at connection start, or only when a specific event fires, rather than refreshed on every PLC scan. The authoritative Siemens guidance is that the application program is responsible for preparing all status values outside the TCP block; the OUC instructions are transport primitives, not state machines. The correct architecture is to assign the input process image to the send buffer continuously, every scan, so the buffer always reflects the current input state.

The fact that "Q0.0, Q0.4 and Q0.6" all trigger at once is the most diagnostic clue: in that test the user's physical inputs I0.0, I0.4, I0.6 and I1.0 were all TRUE, and the send buffer contained the accumulated set bits from earlier S-coil operations. The entire input byte (IB0 plus the low bit of IB1) was effectively transmitted. The case where "Q0.0 – Q0.7 was all triggered on" with only I0.0 true is the worst-case residual: the send DB was initialised to 16#FF somewhere upstream, and the user is moving the full byte to QB0 without ever clearing it.

Critical engineering rule: TCP does not preserve any notion of "the bit I care about." TCP guarantees that the eight-bit byte you put into the buffer at the sender arrives as the same eight-bit byte at the receiver. If you put a byte containing 0b01010011 into the buffer, the receiver gets exactly 0b01010011. Bits 0, 1, 4 and 6 will all be applied to outputs by the cycle-end OB1 process image update.

3. TCP Open User Communication Architecture on the S7-1200

Open User Communication (OUC) is the standard mechanism on the S7-1200 family (CPU firmware V4.0 and above) for transporting raw user data over Ethernet using TCP, UDP, or ISO-on-TCP (RFC 1006). The two instruction blocks of interest are:

Block Function Typical use
TSEND_C (FB / instruction) Send with built-in connection establishment and tear-down Active partner initiates the TCP connection
TRCV_C (FB / instruction) Receive with built-in connection management Active or passive partner receives the data
TSEND (FB / instruction) Send on an existing connection Used after TSEND_C has established the connection
TRCV (FB / instruction) Receive on an existing connection Used after TRCV_C has established the connection
TCON, TDISCON, T_RESET Low-level connection primitives Manual connection lifecycle control

For a TCP point-to-point link where PLC 1 is the active partner and PLC 2 is the passive partner, the data flow is as follows:

  1. PLC 1 calls TSEND_C with REQ = TRUE. The block performs the TCP three-way handshake (SYN, SYN-ACK, ACK) against the configured remote IP and port.
  2. PLC 2 calls TRCV_C in passive (server) mode on its configured local port. The block accepts the incoming connection.
  3. PLC 1 loads the configured LEN bytes from the start of the configured send DB (e.g., DB_iSend) and pushes them to the TCP stack. TSEND_C sets DONE = TRUE for one cycle on success.
  4. PLC 2 receives the bytes and places them in its configured receive DB (e.g., DB_iRcv) starting at the configured offset. TRCV_C sets DONE = TRUE and provides the actual received length in RCVD_LEN.
  5. The application program in PLC 2 reads the byte(s) of interest from the receive DB and copies them to the output process image (QB0 in this case).

The connection configuration (local port, remote IP, remote port, connection ID, active/passive role) is set in the TSEND_C / TRCV_C instance DB through the inspector window in TIA Portal, and the underlying connection is created automatically in the device configuration under Properties > Ethernet addresses > PROFINET interface > Open User Communication.

4. Hardware and Software Prerequisites

Component Specification Notes
PLC 1 (sender) S7-1200 CPU with integrated PROFINET interface (e.g., CPU 1214C DC/DC/DC, part number 6ES7214-1AG40-0XB0) Firmware V4.0 or later required for OUC; V4.2 or later recommended
PLC 2 (receiver) S7-1200 CPU with integrated PROFINET interface (e.g., CPU 1215C AC/DC/RLY, part number 6ES7215-1BG40-0XB0) Same firmware family recommended
Signal modules SM 1223 DI8/DQ8 or equivalent on each CPU Provides the I0.0 and Q0.0 terminals used in the example
Ethernet cable Cat 5e or higher, crossover not required (Auto-MDIX on PROFINET port) Maximum 100 m segment length per IEEE 802.3
Engineering station PC with TIA Portal V16 / V17 / V18 installed Firmware V6.0 of CPU 1214C / 1215C uses TIA Portal V17 SP1 or later
IP addresses PLC 1: 192.168.0.10 / 24, PLC 2: 192.168.0.11 / 24 Same subnet, gateway optional for direct connection
Firewall Disable Windows firewall on the engineering PC for commissioning; PLC firewall not applicable Confirm that corporate firewall is not blocking TCP port 2000 (or custom port)

For firmware-specific behaviour of TSEND_C and TRCV_C, refer to the S7-1200 Programmable Controller System Manual, entry ID 109744817, and the S7-1200 Communication function manual, entry ID 38051505.

5. Connection Configuration in TIA Portal

  1. Open the TIA Portal project containing both PLCs.
  2. Select PLC 1 in the project tree. Open Devices & Networks and click the PROFINET interface of PLC 1.
  3. In the inspector window, choose Properties > Ethernet addresses > IP protocol and set the IPv4 address (e.g., 192.168.0.10) and subnet mask (255.255.255.0).
  4. Repeat for PLC 2 with 192.168.0.11 / 255.255.255.0.
  5. Create a new connection under Devices & Networks > Connections with type "TCP connection". Assign PLC 1 as the active partner and PLC 2 as the passive partner. Note the Connection ID generated (e.g., 1) and the local/remote TSAP or port (e.g., local port 2000, remote port 2000).
  6. Compile and download the hardware configuration to both PLCs.
Tip: The Connection ID in the TIA Portal connection editor must match the ID input on the TSEND_C / TRCV_C instruction instance. A mismatch produces error code W#16#8085 or W#16#80A1 at the STATUS output of the block.

6. Send-Side PLC Program (PLC 1)

The sending PLC 1 must refresh the send data block every scan from the current input process image. The minimum correct implementation is a single MOVE instruction that copies the input byte IB0 to the first byte of the send DB. The example below uses Ladder Diagram (LAD) inside OB1:

Network 1: Continuous input-to-buffer refresh
  |     IB0      DB_iSend.DBB0     |
  |-----[ ]--------------------(MOVE)--------|
  |                                          |
  |  // MOVE IB0 to DBB0 of iSend DB         |

Network 2: TSEND_C trigger (rising edge of REQ)
  |  M0.0 (clock_1Hz)            TSEND_C_DB   |
  |-----(P)---------------------(TSEND_C)-----|
  |    +-------+                                |
  |    |  REQ  |--- TRUE                        |
  |    |  ID   |--- 1       // Connection ID    |
  |    |  LEN  |--- 1       // 1 byte           |
  |    |  DATA |--- P#DB_iSend.DBX0.0 BYTE 1    |
  |    |  DONE |--> Q0.0 local heartbeat LED   |
  |    |  BUSY |--> M10.0                      |
  |    |  ERROR|--> M10.1                      |
  |    |  STATUS|--> MW12                      |
  |    +-------+                                |

The same network in Structured Text (SCL) is:

// Continuous input-to-buffer refresh
DB_iSend.DBB0 := IB0;

// One-shot trigger to avoid re-arming the same send while busy
IF NOT "TSEND_C_Instance".BUSY THEN
    "TSEND_C_Instance".REQ := TRUE;
ELSE
    "TSEND_C_Instance".REQ := FALSE;
END_IF;

Key engineering points:

  • Use a process image update (the default OB1 execution order) so that the most recent value of IB0 is in the input process image at the moment the MOVE executes. If you are reading a digital input module that does not update the process image automatically, call UPDAT_PI in the program.
  • Avoid S/R coils on individual bits of DB_iSend. The S/R coil latches the bit; once latched, the bit will not follow the input.
  • Avoid writing to a single bit of the byte while the rest of the byte retains stale data. Either initialise the entire byte in OB100 (startup) to 16#00, or — preferably — overwrite the entire byte in OB1 every cycle.
  • The TSEND_C block can be triggered on a 100 ms or 200 ms cycle. Triggering it every scan is permitted but wastes CPU time and generates high network traffic; 100 ms is the typical compromise for digital I/O mirroring.

7. Receive-Side PLC Program (PLC 2)

The receiving PLC 2 must copy the relevant byte from the receive DB to the output process image every scan. The minimum correct implementation is a single MOVE that copies DBB0 of the receive DB to QB0:

Network 1: Continuous buffer-to-output refresh
  |   DB_iRcv.DBB0        QB0       |
  |-------[ ]-----------(MOVE)------|

Network 2: TRCV_C call
  |  TRUE                    TRCV_C_DB   |
  |-------------------------(TRCV_C)-----|
  |    +-------+                           |
  |    |  EN_R |--- TRUE                   |
  |    |  ID   |--- 1     // Connection ID |
  |    |  LEN  |--- 1     // 1 byte        |
  |    |  DATA |--- P#DB_iRcv.DBX0.0 BYTE 1|
  |    |  DONE |--> M20.0                  |
  |    |  BUSY |--> M20.1                  |
  |    |  ERROR|--> M20.2                  |
  |    |  STATUS|--> MW22                  |
  |    |  RCVD_LEN|--> MW24               |
  |    +-------+                           |

Equivalent Structured Text:

// Continuous buffer-to-output refresh
QB0 := DB_iRcv.DBB0;

By writing the entire byte QB0 from the receive byte, the application enforces a 1:1 mirror of the sender's input byte. If only a single output is required (Q0.0 only), use bit extraction instead:

// Single-bit mapping: only Q0.0 follows I0.0 of PLC 1
Q0.0 := DB_iRcv.DBX0.0;

This explicit bit-by-bit mapping is the safest pattern in production because the other seven bits of QB0 remain under local program control and are not overwritten by the TCP payload.

8. Data Buffer Layout and Byte Mapping

Define the two data blocks with explicit byte offsets. Below is the recommended declaration in the DB properties of TIA Portal (Properties > Attributes > Optimised block access may be unchecked for direct byte access, or kept enabled for symbolic access):

DB name Symbol Offset Type Initial value Direction
DB_iSend SendBuffer 0.0 BYTE 16#00 PLC 1 → PLC 2
DB_iSend SendBuffer 1.0 BYTE 16#00 PLC 1 → PLC 2 (reserved / future)
DB_iRcv RcvBuffer 0.0 BYTE 16#00 PLC 2 <- PLC 1
DB_iRcv RcvBuffer 1.0 BYTE 16#00 PLC 2 <- PLC 1 (reserved / future)

Set LEN = 1 on both TSEND_C and TRCV_C. Initialising the buffer to 16#00 in the DB declaration ensures that even if a single-bit copy were used by mistake, the residual bits are forced to '0' and will not trigger stray outputs.

Consistency note: When the application grows beyond 8 bits, increase LEN to 2 (for 16 bits) and use DBW0 as the data reference, or 4 for 32 bits with DBD0. Always keep the LEN value identical on both PLCs; a mismatch produces a length error (STATUS = W#16#8088 on TSEND_C, W#16#8088 on TRCV_C).

9. Verification and Commissioning Procedure

  1. Online connection check. In TIA Portal, go online with both PLCs. Open the watch table containing the TSEND_C and TRCV_C instance DBs. Confirm STATUS = 16#0000 and BUSY = FALSE on both blocks. The DONE bit should pulse TRUE for one cycle each time a send or receive completes.
  2. Bit-level walk test. Force I0.0 = TRUE on PLC 1. Confirm QB0 on PLC 2 reads 16#01 (binary 0000 0001). Force I0.0 = FALSE. Confirm QB0 on PLC 2 returns to 16#00 within 200 ms (one send cycle).
  3. Multi-bit walk test. Force I0.0 = TRUE, I0.4 = TRUE, I0.7 = TRUE on PLC 1. Confirm QB0 on PLC 2 reads 16#91 (binary 1001 0001). Verify the other bits of QB0 (Q0.1, Q0.2, Q0.3, Q0.5, Q0.6) remain at the level of PLC 2's local program.
  4. Edge case: dynamic I/O. Toggle I0.0 at 1 Hz using a clock bit. Verify the LED on Q0.0 of PLC 2 (if wired) blinks at the same frequency with no latching and no spurious outputs.
  5. Connection-loss test. Disconnect the Ethernet cable. After the configured keep-alive timeout (default 30 s), the TSEND_C STATUS output should report a connection error (commonly W#16#80A1 or W#16#80C3). Reconnect the cable and confirm the connection re-establishes and the output resumes correct mirroring within 5 s.
  6. Power-cycle test. Power-cycle PLC 2 only. With PLC 1 still running and refreshing the send buffer, PLC 2 should re-establish the connection on restart (because TRCV_C is called in OB1) and resume mirroring within 2–3 s of reaching RUN mode.

10. Common Pitfalls and Edge Cases

Symptom Likely cause Corrective action
Output latches ON after first TRUE S/R coil on individual bit of send DB, never reset Replace S/R with continuous MOVE from input byte
Multiple outputs trigger at once Entire receive byte written to QB0 with non-zero residual bits Use single-bit mapping (Q0.0 := DBX0.0) or initialise DB to 0 and overwrite full byte
Output never updates Connection not established; TSEND_C STATUS ≠ 0 Check IP / port / Connection ID / firewall
Output flickers LEN mismatch between send and receive; partial frames Set LEN identically on TSEND_C and TRCV_C
Connection drops after ~30 s Keep-alive not configured or network path blocked Configure "Connection monitoring" in TCON properties; verify router/switch allows TCP port
Initial state is all bits ON at startup DB initial values non-zero Set all DB bytes to 16#00 in declaration; force a MOVE 0 to QB0 in OB100
Input from PLC 1 changes but output on PLC 2 does not Send trigger not firing (e.g., clock bit off, or REQ latched on with BUSY) Use edge-triggered one-shot (P coil) or check BUSY before asserting REQ
Output mirrors an adjacent input (e.g., I0.1 triggers Q0.0) Byte order or offset mismatch between DB declaration and TSEND_C DATA pointer Verify P# pointer (P#DB_iSend.DBX0.0 BYTE 1) matches the intended offset

11. Diagnostic Block Status and Error Codes

Both TSEND_C and TRCV_C write a 16-bit STATUS word on every cycle. The most common status codes for this application are:

STATUS (hex) Meaning Recommended action
W#16#0000 No error, block idle None; normal operation
W#16#7000 No job active None; block waiting for REQ or incoming connection
W#16#7001 Job started, connecting Wait for state transition
W#16#7002 Connection established, data being sent/received None; transient
W#16#7003 Connection being terminated None; transient
W#16#8085 Connection ID parameter error (ID input) Verify Connection ID matches the value in the TIA Portal connection editor
W#16#80A1 Connection not established or aborted by remote Check partner IP, partner port, and physical layer
W#16#80C3 Connection aborted by local user (TDISCON, power-down) Check for explicit TDISCON call or controller STOP
W#16#80C4 Connection temporarily aborted (resource shortage) Reduce number of concurrent OUC connections on the CPU
W#16#8088 LEN parameter error Verify LEN is > 0 and ≤ the size of the configured data area

Always create a watch table that includes the STATUS word, BUSY, DONE, ERROR, and (for TRCV_C) RCVD_LEN for both blocks. Add the watch table to the project so that field engineers can connect via TIA Portal or HMI and immediately see the live state of the TCP link without needing to open the program blocks.

Security note: Open User Communication on the S7-1200 supports TLS-protected variants via the OPC UA server of the CPU (firmware V4.4 and later) or via TCONFIG-based secure TCP. For a plain TCP trigger, the payload is unauthenticated and unencrypted. Do not use this pattern for safety-relevant signals (SIL 1 or higher per IEC 61508); for safety I/O, use PROFIsafe over PROFINET instead.

12. Frequently Asked Questions

Why does my Q0.0 stay ON after I0.0 returns to FALSE?

The send-side buffer is not being refreshed. Replace any Set/Reset coil logic on the send DB with a continuous MOVE from the input process image (e.g., DB_iSend.DBB0 := IB0; in SCL). TCP only transports whatever byte is in the buffer at the moment of the send; it never modifies the buffer for you.

Why are Q0.4 and Q0.7 also turning ON when only I0.0 is wired?

Your application is writing the entire receive byte to QB0, so every bit in the receive byte drives its corresponding output. Either initialise the send DB to 16#00 in OB100 and use single-bit mapping on the receive side (e.g., Q0.0 := DB_iRcv.DBX0.0;), or copy only the relevant byte to the relevant QB and leave the other outputs under local control.

What LEN value should I use to mirror one bit?

Use LEN = 1 and send a single BYTE containing the eight input bits. Extract the single bit you need on the receive side. Sending individual bits is not supported by TSEND_C; the block always sends whole bytes starting at the configured offset.

Can PLC 1 be the passive partner and PLC 2 the active partner?

Yes. In the TIA Portal connection editor, swap the active/passive role and adjust the local/remote port assignments accordingly. The TSEND_C and TRCV_C calls move to PLC 2, and PLC 1 hosts the TRCV_C in server mode. The application logic on each side does not change.

How fast can the I0.0 → Q0.0 mirror run?

On an S7-1200 CPU 1214C / 1215C with default PROFINET scan and a 100 ms send cycle, end-to-end latency is approximately 120–250 ms including input debounce, scan time, send time, network transit, and receive processing. For sub-10 ms latency, use PROFINET I-Device coupling (entry ID 109478798) or PROFIsafe over PROFINET.

Back to blog