1. Overview
The SIMATIC S7-1200 supports peer-to-peer Ethernet data exchange between two CPU 1214C (or any S7-1200/S7-1500 combination) controllers using the TSEND_C and TRCV_C instructions from the "Communication" palette in TIA Portal. TSEND_C/TRCV_C are compact versions of the older TUSEND/TURCV pair and internally handle the connection establishment (TCON), termination (TDISCON), and option-byte handling. The transport protocol is ISO-on-TCP (RFC 1006) by default, which provides acknowledged, connection-oriented, point-to-point data transfer over the PROFINET interface of the CPU.
This reference applies specifically to a two-CPU 1214C topology (TIA Portal V11 or later), an unmanaged switch, and a default firmware of the S7-1200 family. The article resolves two recurring field issues:
- The TSEND_C CONNECT input rejecting every data block with "incompatible data type".
- Values written from an HMI tag are not propagated to the partner PLC, while values written from the program ARE propagated.
2. Prerequisites
| Item | Specification |
|---|---|
| Controller A (active/client) | CPU 1214C DC/DC/DC or DC/DC/RLY, FW 4.0 or higher recommended for TIA V11-V16 compatibility |
| Controller B (passive/server) | CPU 1214C, same firmware family |
| Engineering | TIA Portal V11 SP2 Update 5 or later (V13, V14, V15, V16, V17 supported with the same block interface) |
| Network | Unmanaged 100 Mbit/s switch, CAT5e or higher, point-to-point works without a switch using a crossover or auto-MDI(X) cable |
| IP addresses | 192.168.0.1 / 255.255.255.0 and 192.168.0.2 / 255.255.255.0 (must be in the same subnet) |
| Open communication connections | CPU 1214C supports up to 8 active and 8 passive Open User Communication connections; this project uses 1 of each |
| Block library version | TSEND_C V3.0 / TRCV_C V3.0 (auto-installed with TIA Portal) |
3. Network Topology and IP Planning
Both controllers MUST reside in the same IP subnet. ISO-on-TCP uses port 0x1024 (decimal 1024) as TSAP for S7-1200; you may freely select local and remote TSAPs (16 bits each) provided that the active and passive sides mirror one another.
4. Configuring the Connection in TIA Portal
The most common beginner error is wiring the CONNECT input to a user-defined data block of the wrong structure. Siemens requires a TCON_IP_V4 System Data Type (SDT) data block. There are two ways to generate it:
- Right-click the CPU in "Devices & Networks" and add an "ISO-on-TCP connection" between the two PLCs. TIA Portal auto-creates the connection data block.
- Manually add a new global DB, declare a single
CONNECTvariable of typeTCON_IP_V4(V3.0), and fill the parameters.
Recommended path (Method 1):
- Open "Devices & Networks" view of PLC_A.
- Drag a connection line from the PROFINET port of PLC_A to PLC_B.
- Choose "ISO-on-TCP connection" from the popup.
- Click the connection line, go to Properties → General, and note the Connection ID (default = 1).
- In PLC_A's project tree, expand "Program blocks → System blocks → Additional system blocks". A new DB named
SENDCONNECTION_1(or similar) appears. This is the DB you wire to the TSEND_C CONNECT input.
5. TSEND_C Block Parameters
| Input | Data type | Meaning | PLC_A example |
|---|---|---|---|
| REQ | BOOL | Rising edge starts a send job |
SendTrigger (edge-detected) |
| ID | CONN_OUC | Connection reference from TCON | 1 (from Devices & Networks) |
| CONNECT | TCON_IP_V4 | Connection description (auto-DB) | "SENDCONNECTION_1".CONNECT |
| DATA | VARIANT | Pointer to send area (DB / M / I/Q) | "DataDB".SendBuffer |
| LEN | UINT | Number of bytes to send | 100 |
| CONT | BOOL | Keep connection after send (TRUE = keep open) | TRUE |
| Output | Data type | Meaning |
|---|---|---|
| DONE | BOOL | One-cycle TRUE after successful send |
| BUSY | BOOL | TRUE while job is in progress |
| ERROR | BOOL | TRUE if the job failed |
| STATUS | WORD | Status / error code (see diagnostics table) |
6. TRCV_C Block Parameters
| Input | Type | Meaning | PLC_B example |
|---|---|---|---|
| EN_R | BOOL | Enable reception (TRUE = always ready) | TRUE |
| ID | CONN_OUC | Connection reference | 1 |
| CONNECT | TCON_IP_V4 | Connection description | "RCVCONNECTION_1".CONNECT |
| DATA | VARIANT | Receive area (must be large enough) | "DataDB".RecvBuffer |
| LEN | UINT | Max bytes to receive (0 = accept any length) | 0 (use 100 if you want fixed-length) |
| ADHOC | BOOL | Copy partial frames immediately | TRUE |
7. TCON_IP_V4 Connection Description
The "incompatible data type" error in the CONNECT input almost always means the user created a DB with the wrong UDT or used TCON_IP_V4 from a different version. The TIA Portal V11-V17 SDT contains:
TYPE TCON_IP_V4
VERSION : 3.0
STRUCT
InterfaceId : HW_ANY; // PROFINET interface HW identifier, usually 64
ConnectedMcId : BYTE; // Multicast ID, 0 = unicast
LocalPort : UINT; // Local TSAP / port (e.g. 0x1024)
RemoteAddress : IP_V4_STRUCT; // 4 bytes + 2 bytes for port
LocalAddress : IP_V4_STRUCT; // optional, fill with 0.0.0.0
ConnectionType : BYTE; // 0x11 = TCP, 0x12 = ISO-on-TCP, 0x13 = UDP
ActiveEstablished : BOOL; // TRUE = active (client), FALSE = passive (server)
END_STRUCT
END_TYPE
Set ConnectionType = 0x12 for ISO-on-TCP. Set ActiveEstablished = TRUE on the TSEND_C side and FALSE on the TRCV_C side. The RemoteAddress must contain the partner's IP in network byte order (e.g. 192,168,0,2 + port 0x0000, port field stays 0 for ISO-on-TCP because TSAPs use LocalPort/RemotePort in the next fields).
8. Ladder / SCL Sample Code
PLC_A (sender, OB1 main scan):
// Edge-detect a "send now" trigger
A M10.0 // Send request from HMI / program
FP M10.1 // Edge memory bit
= "SendTrigger"
// Call TSEND_C
CALL "TSEND_C_DB" , "TSEND_C_INST"
REQ := "SendTrigger"
ID := 1
CONNECT:= "SENDCONNECTION".CONNECT
DATA := "DataDB".SendBuffer
LEN := 100
CONT := TRUE
DONE => "StatDB".SendDone
BUSY => "StatDB".SendBusy
ERROR => "StatDB".SendError
STATUS => "StatDB".SendStatus
PLC_B (receiver, OB1 main scan):
// Always ready to receive
SET
= "RecvEnable"
CALL "TRCV_C_DB" , "TRCV_C_INST"
EN_R := "RecvEnable"
ID := 1
CONNECT:= "RCVCONNECTION".CONNECT
DATA := "DataDB".RecvBuffer
LEN := 0
ADHOC := TRUE
DONE => "StatDB".RecvDone
BUSY => "StatDB".RecvBusy
ERROR => "StatDB".RecvError
STATUS => "StatDB".RecvStatus
RCVD_LEN => "StatDB".RecvLen
9. Root Cause: HMI-Triggered Values Do Not Reach Partner PLC
This is the second and most common production symptom: a value written into SendBuffer by the PLC program is correctly transmitted to the partner, but a value written by the HMI is not. The reason is purely about REQ edge behavior.
TSEND_C is edge-triggered. The send job executes exactly once per rising edge on REQ. The CPU only sends the current content of DATA at that moment. Two scenarios occur in the field:
- HMI writes a new value, but REQ does not pulse — TSEND_C has no reason to fire, so the partner keeps the old data.
- Program logic only sets REQ when a "process event" occurs — a value change alone does not generate an edge.
Typical cause: the program uses a button-driven or event-driven REQ (e.g. M10.0 set when a sensor trips) but the HMI just writes to DataDB.SendBuffer directly, without pulsing any send trigger.
10. Fix: HMI-Side Change Detection / Cyclic Send
Three proven solutions, ordered from most elegant to most brute-force:
10.1 Trigger REQ on every value change (recommended)
Add a "send enable" or "send on change" tag. In PLC_A, compare SendBuffer to a shadow copy. If a difference is detected, pulse REQ:
// In OB1 of PLC_A
"Shadow".LastSent := "Shadow".LastSent OR 0;
IF "DataDB".SendBuffer <> "Shadow".LastSent THEN
"Shadow".ChangeDetected := TRUE;
END_IF;
// Edge detect the change flag
IF "Shadow".ChangeDetected THEN
"SendTrigger"(FP := "Shadow".EdgeMem); // SCL one-shot
"Shadow".ChangeDetected := FALSE;
"Shadow".LastSent := "DataDB".SendBuffer;
END_IF;
With this block in place, an HMI write to DataDB.SendBuffer will automatically trigger a transmission on the next PLC cycle.
10.2 Use a polling / heartbeat send
Send the entire buffer on a fixed time base (e.g. every 200 ms using a clock bit from OB35 or a self-generated flasher). This guarantees eventual consistency regardless of HMI writes:
// Using CPU clock memory, byte 1000 - bit 5 = 2 Hz
// 2 Hz is too fast for ISO-on-TCP, scale to 0.5 Hz via TON
"Clock_2Hz"( TP := 200ms, Q => "HalfHz" );
IF "HalfHz" THEN
"SendTrigger"(FP := "EdgeSend");
END_IF;
10.3 Make the HMI pulse the send trigger
Bind the HMI button (or "value changed" event of the input field) to set a dedicated tag such as HMI_SendRequest for one cycle. The PLC detects the edge and fires TSEND_C. This is the least preferred approach because the HMI must know about the trigger variable, coupling display logic to communication logic.
11. Common TSEND_C / TRCV_C Status Codes
| STATUS (hex) | Meaning | Remediation |
|---|---|---|
| 0x0000 | No error | — |
| 0x7000 | No job in progress (DONE/BUSY/ERROR all 0) | Normal idle |
| 0x7001 | Job started, waiting for execution | Normal |
| 0x7002 | Job running | Normal |
| 0x8085 | LEN parameter invalid (0, negative, or > LEN of source area) | Use UINT length matching buffer size |
| 0x8086 | ID parameter invalid (connection not configured) | Re-create connection in Devices & Networks |
| 0x80A1 | Connection / port in use | Check partner PLC is reachable, no duplicate connection IDs |
| 0x80C3 | All connection resources exhausted (CPU limit hit) | Reduce Open User Communication count to 8 active / 8 passive |
| 0x80C4 | Temporary connection error (TCP RST, partner not ready) | Check TSAP / IP, partner TRCV_C EN_R, partner CPU in RUN |
| 0x80C7 | Send data length exceeds local send buffer | Reduce LEN |
| 0x80D0 | Connection was terminated by TDISCON or partner | Check partner CPU RUN state, reset both controllers |
| 0x80E0 | Connection is currently being set up (BUSY) | Wait for DONE or ERROR |
| 0x80E9 | Connection setup rejected by partner | Check TSAP mismatch: ISO-on-TCP TSAPs must swap between partners |
| 0x8181 | Data length differs from LEN in receive | Set LEN = 0 (length received with the frame) and inspect RCVD_LEN |
12. Diagnostic Procedure
- Online → Diagnostics → Statistics in TIA Portal on the PROFINET interface of PLC_A: verify the partner IP appears as reachable.
- Open a watch table on PLC_A. Monitor
StatDB.SendBusy,SendError,SendStatus. After pulsing REQ once, BUSY should pulse to TRUE for one cycle and DONE to TRUE on success. - On PLC_B, monitor
RecvDoneandRecvLen. After a successful send, RecvDone = TRUE for one cycle and RecvLen = number of bytes transferred. - If BUSY stays TRUE for > 5 s, STATUS will report a connection error (0x80C4, 0x80E9). Capture the hex and cross-reference Section 11.
- Open the S7-1200 "Diagnostics buffer" (online → Diagnostics buffer). The connection event includes the partner IP and the failing TSAP.
13. Verification Checklist
| Step | Expected Result | Pass criteria |
|---|---|---|
| Compile & download both PLCs | No compile errors, both in RUN | OK / Pass |
| Online → Connections | Connection ID 1 listed as "Established" | Status green |
| Program-triggered send | Partner value updates within 2 cycles | RecvDone = TRUE |
| HMI-triggered write | Partner value updates after change-detect logic fires | RecvDone = TRUE within 1 scan of the change |
| Cold restart both PLCs | Connection re-establishes within 5 s | BUSY → DONE |
| Disconnect Ethernet cable for 10 s and reconnect | STATUS reports 0x80D0 briefly, then DONE | Auto-recovery to 0x0000 |
14. Field-Proven Caveats
- Do not place TSEND_C in OB1 with REQ tied to
TRUE— the CPU will send at line speed and exhaust the Open User Communication buffer. Always use a finite-edge trigger or a timer. - TRCV_C with
LEN = 0andADHOC = TRUEis the most robust receive pattern: partial frames are copied immediately andRCVD_LENreports the actual number of bytes received. Use this for variable-length messages. - ISO-on-TCP TSAPs are 16-bit. The S7 convention is to put CPU slot number in the second byte (e.g.
01.01= rack 1 slot 1). For a CPU 1214C use01.01; this avoids collisions if you later add a CM module. - Two TSEND_C blocks with the same Connection ID cause STATUS = 0x80A1. Always use unique connection IDs for each partner.
- CPU 1214C FW 4.0 and earlier will accept only the V1.0 SDT
TCON_IP_V4structure. If upgrading the project to a newer TIA Portal, right-click the block → "Update to latest version" to remap the structure. - The same logic applies when the partner is a S7-1500. The block interfaces are identical; the only thing that changes is the maximum number of Open User Communication connections (S7-1500 supports far more).
15. Related Protocols
TSEND_C/TRCV_C are ISO-on-TCP only. If the requirement is to talk to a third-party device that does not support RFC 1006 (e.g. a SCADA system that expects raw Modbus/TCP or a generic TCP socket), use:
- MODBUSCLIENT / MODBUSSERVER instructions for Modbus TCP on the same S7-1200.
- TSEND / TRCV (the older, non-compact pair) for raw TCP without ISO-on-TCP header.
- Open User Communication as UDP with TUSEND/TURCV for non-acknowledged broadcasts.
Why does TSEND_C reject every data block with "incompatible data type" on the CONNECT input?
The CONNECT input expects a variable of data type TCON_IP_V4 (V3.0 in modern TIA Portal). A user-defined DB created with the "Add new DB" wizard has the wrong structure. The fix is to let TIA Portal create the connection DB automatically: in "Devices & Networks", drag an ISO-on-TCP connection between the two PLCs and use the system-generated DB as the CONNECT source. This guarantees the right SDT version is used.
Values written from my program reach the partner PLC, but HMI writes do not. Why?
TSEND_C is edge-triggered on REQ. A value change alone does not transmit — a rising edge on REQ is required. The HMI is writing into the same data area, but no edge is being generated. Add a change-detection block in the sender PLC that compares the current value to a shadow copy and pulses REQ on difference, or trigger a cyclic send on a 200-500 ms heartbeat. This makes HMI writes propagate transparently.
What is the default TSAP and port for ISO-on-TCP on the S7-1200?
ISO-on-TCP on the S7-1200 uses TSAPs (Transport Service Access Points), not IP port numbers. The default S7-1200 convention is 01.01 for both local and remote (rack 1, slot 1). The TSAP is configured inside the TCON_IP_V4 structure. If both CPUs use slot 1, the configuration mirrors naturally — local TSAP on PLC_A equals remote TSAP on PLC_B and vice versa.
How many TSEND_C / TRCV_C connections can a CPU 1214C handle?
The CPU 1214C supports up to 8 active and 8 passive Open User Communication connections simultaneously (for ISO-on-TCP, TCP, and UDP combined). This is sufficient for a small multi-PLC network. If you need more, use a S7-1500 or a CM 1243-1 communication module on the S7-1200.
Status 0x80E9 "Connection setup rejected by partner" — how do I fix it?
The local and remote TSAPs do not match correctly. ISO-on-TCP requires the active side to point at the partner's TSAP, and the passive side to listen on a TSAP that matches. Open the TCON_IP_V4 structure on both PLCs and verify that the LocalPort on the active side equals the LocalPort on the passive side, and the RemoteAddress on the active side equals the passive side's local TSAP. Restarting both PLCs after the change is recommended.