Problem Overview
When a Siemens SIMATIC S7-300 CPU 315F-2 PN/DP (firmware V3.2.x) attempts to send print jobs to a Zebra ZM400 industrial label printer over the integrated PROFINET interface using the standard open-TCP communication blocks (FB63 TSEND, FB64 TRECV, FB65 TCON, FB66 TDISCON), the user program repeatedly receives status code 80A1 on the TSEND block. The same status also appears on the TCON status output if connection setup is monitored. Even though the CPU can ping the printer on IP 10.8.100.101 and both devices sit in the same subnet, the TCP socket at the application layer never becomes fully established and no label data is delivered.
Status 80A1 in the Siemens TSEND / TCON family does not mean the cable is bad or the IP stack is broken. It means: "The connection is not yet established – a TSEND/TRECV was issued before TCON reported DONE, or the existing connection was torn down by the partner, by the CPU, or by a restart." The reference numbering of the open TCP/ISO-on-TCP blocks on S7-300/400 is FB63/64/65/66 (TSEND_C, TRCV_C, TSEND, TRCV, TCON, TDISCON). On S7-300 firmware V3.x the legacy numbering is preserved. For the official Siemens description of the error semantics, see the SIMATIC NET FB63–FB66 block manual and the TCON / TSEND / TRECV programming guideline.
TCON / TSEND in OB1. A Run→Stop→Run without cold restart, or with the connection logic only in OB1, is generally not sufficient on the 315F-2 PN/DP because the integrated PROFINET stack only initialises the open-TCP connection table during the OB100 cold-restart path.Affected Hardware and Firmware
| Item | Value | Notes |
|---|---|---|
| CPU | SIMATIC S7-300 CPU 315F-2 PN/DP | Order number 6ES7315-2FH13-0AB0 (also -2EH13 and -2FG14 variants). The "-F" suffix denotes the fail-safe variant; the PN interface is identical to the non-F part for open-TCP use. |
| CPU firmware | V3.2.x | Integrated PN interface supports up to 16 open TCP / ISO-on-TCP connections, of which 8 can be TCP. Routing is enabled by default in NetPro / HW Config. |
| Integrated interface | PROFINET X2 (RJ45, 2-port switch) | Use X2 P1 or X2 P2 for the printer link. Direct CPU↔printer cabling uses a 1:1 patch cable, not a crossover. |
| Printer | Zebra ZM400 (ZPL II / EPL2) | Default TCP listening port 9100 (raw socket / line-printer daemon). Some firmware revisions additionally expose 9101, 9102, 9103. |
| Engineering tool | STEP 7 V5.5 + SPx or TIA Portal V13+ | The library Communication Blocks (FB63–FB66) ships with STEP 7 and with TIA Portal under Instructions > Communication > Open communication. |
| CP alternative | CP 343-1 Lean / Standard / Advanced (6GK7343-1…) | Only relevant as a fallback; the integrated PN port is the primary path described in this article. |
Root Cause Analysis
Error 80A1 on a 315F-2 PN/DP is almost always one of three layered causes. They can occur in isolation or in combination.
-
Connection establishment is not requested in OB100. The integrated PROFINET stack of the 315F-2 PN/DP releases the open-TCP connection table only after OB100 has run once. If the user program only calls
TCONin OB1 and the CPU is in RUN before the connection is up, the firstTSENDcall in OB1 issues against a not-yet-existing connection and returns 80A1. A subsequent Stop→Run (warm restart) does not always rebuild the table – a true cold restart is required. - Local port number is outside the firmware-permitted range or is duplicated. Older firmware revisions of the 315F-2 PN/DP only allow local ports 2000 to 5000 for open-TCP. Even within that range, if a port is reused for two active connections with different IDs, the second TCON will fail with 80A1 because the kernel refuses the second bind. The user program reports 80A1 on the next TSEND against the failed connection.
-
The TCON parameter block (UDT 65 "TCON_PAR") is incomplete or mismatched. The most common field mistakes are:
InterfaceIDpointing to the wrong HW identifier (must be the PROFINET interface, not the PROFIBUS side),ActiveEstablished= TRUE for a connection that should be passive, orConnectionType= 18 (ISO-on-TCP) where the Zebra printer only speaks raw TCP – the partner then resets the socket and the next TSEND returns 80A1.
Connection ID and Local Port Rules
Open-TCP on the 315F-2 PN/DP enforces a flat connection table. Every connection — active or passive — must have a unique connection ID in the range 1 … 4095 (in practice the FB65 input ID). Each unique ID also implies a unique local port if the CPU is the active side. A typical mistake is to reuse ID := 5 across two S7 connections that happen to terminate at the same Zebra – the second TCON replaces the first and the printer sees the second socket as the only valid one, while the first connection state machine in the CPU continues to issue TSEND against a now-orphaned ID, producing 80A1.
| Firmware | Local port range allowed | Notes |
|---|---|---|
| V2.x and earlier | 2000 – 5000 only | Outside this range the bind fails silently and TSEND returns 80A1. |
| V3.0 – V3.2 | 2000 – 5000 recommended; full 1–49151 accepted on most builds | Siemens documentation still recommends 2000–5000 to avoid collisions with system services (RFC 1006, S7, etc.). |
| V3.3+ (CPU 315-2 PN/DP non-F) | 1 – 49151 | Same UDT 65 layout. |
REM_PORT; do not set REM_PORT := 2500 or the Zebra will see an unknown port and reset the connection.UDT 65 (TCON_PAR) Field Reference
The TCON block expects its CONNECT input to point at a data block of type UDT 65 "TCON_PAR". The fields most often wrong on a 315F-2 PN/DP open-TCP project are listed below. Values shown are the values that resolve the 80A1 symptom for a CPU → Zebra ZM400 raw-socket link.
| Field | Data type | Value for Zebra ZM400 link | Comment |
|---|---|---|---|
| BlockLength | WORD | W#16#40 (64 bytes) | Length of the UDT itself; leave at default. |
| Id | WORD | W#16#0005 | Must equal FB65 input ID. 1–4095, project-unique. |
| ConnectionType | BYTE | B#16#11 (TCP, 17 dec) | Use 18 (B#16#12) only for ISO-on-TCP. Zebra ZM400 speaks raw TCP – keep 17. |
| ActiveEstablished | BOOL | TRUE | CPU is the active side and must open the socket. |
| LocalDeviceId | BYTE | B#16#02 | 2 = PROFINET integrated interface of the 315F-2 PN/DP. Do not use B#16#01 – that points at the DP/PN combined MPI/DP port. |
| LocalTSelectorLength / RemoteTSelectorLength | BYTE | 0 | Empty for raw TCP. |
| LocalTSelector / RemoteTSelector | BYTE[32] | all 0 | Empty for raw TCP. |
| RemoteDeviceId | BYTE | B#16#00 | Not evaluated for raw TCP, but set to 0 to be safe. |
| RemoteSubnetIdLength / LocalSubnetIdLength | BYTE | 0 | No subnet routing for a direct 10.8.100.x link. |
| LocalAddress | BYTE[6] | CPU IP + port 2500 (see layout below) | Bytes 1–4 = IP octets, bytes 5–6 = port high/low. |
| RemoteAddress | BYTE[6] | 10,8,100,101, 35,136 (port 9100 = 0x2388) | Zebra IP 10.8.100.101, port 9100. |
LocalAddress byte layout for the CPU side (port 2500 = 0x09C4):
LocalAddress[1] = B#16#0A // 10
LocalAddress[2] = B#16#08 // 8
LocalAddress[3] = B#16#64 // 100
LocalAddress[4] = B#16#01 // 1 (CPU's own IP — fill with whatever the CPU actually has)
LocalAddress[5] = B#16#09 // 2500 high
LocalAddress[6] = B#16#C4 // 2500 low
Step-by-Step Solution
The fix is the same regardless of whether you build the user program in STEP 7 V5.5 with the legacy F-library or in TIA Portal V13+ with the Open Communication instructions. The sequence is: (1) configure HW, (2) drop the right FB in OB100, (3) drop the cyclic FBs in OB1, (4) cold-restart, (5) watch DONE.
Step 1 — Hardware and network configuration
- In HW Config / device view, open the PROFINET interface properties of the CPU. Confirm IP address (e.g. 10.8.100.1) and Subnet mask 255.255.255.0. The Zebra ZM400 must be in the same subnet (10.8.100.101 / 24).
- Open Options > Configure Network (NetPro) and select the PROFINET subnet. Do not enable routing for an open-TCP link – routing is a Layer-3 service and is not needed for a same-subnet CPU↔printer socket. (Routing can coexist, but on V3.2 it occasionally causes TCON timeouts that surface as 80A1.)
- Verify with
ping 10.8.100.101from a programming PC and a separatePG/OP connectionping from the CPU's online diagnostics. Both directions must succeed. Unidirectional ping = duplex mismatch, almost always a bad patch cable or a forced-100 Mb/s negotiation on one side.
Step 2 — Place the connection-establishment logic in OB100
This is the operationally critical step. Create or open OB100 (Complete Restart / Cold Restart) in your S7 program. Place a single call of FB65 TCON there with the UDT 65 parameter block described above. Example call (STEP 7 classic STL notation shown for clarity; TIA Portal uses the same inputs through the instruction box):
// OB100 — complete restart
CALL FB65 "TCON" // Open TCP connection
REQ :=TRUE // Fire on every cold restart
ID :=W#16#5 // Connection ID 5, must be unique
DONE :=M100.0 // Becomes TRUE once the socket is up
BUSY :=M100.1
ERROR :=M100.2
STATUS :=MW102 // 80A1 / 80A7 / 0000 etc.
CONNECT:="TCON_PAR_ZM400".TCON_PAR // UDT 65 in instance DB
Step 3 — Place cyclic TCON / TSEND / TRECV in OB1
OB1 is the cyclic supervisor. It must re-issue TCON while DONE = FALSE and only start firing TSEND once DONE = TRUE. Recommended logic:
// OB1 cyclic
// 1. Hold TCON active until DONE
A M100.0 // DONE
JC SEND // If socket up, skip TCON call
CALL FB65 "TCON"
REQ :=TRUE
ID :=W#16#5
DONE :=M100.0
BUSY :=M100.1
ERROR :=M100.2
STATUS :=MW102
CONNECT:="TCON_PAR_ZM400".TCON_PAR
SEND: NOP 0
// 2. Only call TSEND when DONE = TRUE and the print buffer is non-empty
A M100.0 // DONE
A "PRINT_REQ" // Trigger from HMI / recipe
JC DO_SEND
JU RCV
DO_SEND: CALL FB63 "TSEND"
REQ :="PRINT_REQ"
ID :=W#16#5
LEN :="PRINT_LEN" // Byte length of the ZPL command string
DATA :=P#DB100.DBX0.0 BYTE 200 // ZPL II command buffer
DONE :=M104.0
BUSY :=M104.1
ERROR :=M104.2
STATUS :=MW106
RCV: CALL FB64 "TRECV"
ID :=W#16#5
LEN :=200
DATA :=P#DB101.DBX0.0 BYTE 200
NDR :=M108.0
ERROR :=M108.2
STATUS :=MW110
LEN_R :=MW112
Step 4 — Cold-restart the CPU
- From STEP 7 / TIA Portal: Online > CPU Operating Mode > Cold Restart. Confirm the CPU prompt. The CPU goes to STOP, executes OB100 (where the TCON is fired), then transitions to RUN.
- Watch
STATUSin VAT. After 1–3 OB1 cycles the value must change from80A1to0000and theDONEbit must rise. 80A7 during the transition means the Zebra closed the socket – check cabling and printer IP. - Force a one-shot ZPL command through, e.g.
^XA^FO50,50^A0N,50,50^FDHello^FS^XZ. Verify the label prints.
Step 5 — Persist the connection across power-cycle
Place the same OB100 TCON call in OB101 (Restart / Warm restart) as well. On 315F-2 PN/DP firmware V3.2, the open-TCP table is not rebuilt automatically across a warm restart. OB101 ensures the connection is re-issued if the operator only triggers a restart and not a full cold restart.
Verification Procedure
| Check | Expected result | What it confirms |
|---|---|---|
| TCON STATUS after cold restart |
W#16#0000 within 2 s, DONE = TRUE |
TCP socket is established at the OS level. |
| Zebra ZM400 web interface > Network > TCP connections | One entry from CPU IP, state ESTABLISHED, local port 2500 / remote 9100 | End-to-end path is up. |
| TSEND with 1 ZPL string | DONE = TRUE, STATUS = 0000, label prints | Application layer works. |
| Zebra ZM400 print log | New entry timestamp matches the TSEND trigger | No packet loss at the application layer. |
| Power-cycle CPU (MRES not used) | Connection re-establishes within 3 s after OB100 + OB1 | OB100 init logic is correct. |
Extended Troubleshooting Matrix
| Symptom | Likely cause | Remedy |
|---|---|---|
| TSEND = 80A1 from power-up, never goes to 0000 | TCON never called in OB100/OB101 | Add TCON to OB100, do a cold restart. |
| TSEND = 80A1, then 80A7, then 80A1 cycling | Printer port 9100 closed or wrong IP | From a PC: telnet 10.8.100.101 9100; if that fails, check Zebra network configuration. |
| TSEND = 80B5 (resource shortage) | More than 8 active TCP connections on the integrated PN | Reduce active connections or move some to a CP 343-1. |
| TSEND = 80A1 only on the second CPU start, not the first | Local port collision – same port used by another application on the CPU | Use a different local port (e.g. 2501) and a different connection ID. |
| TSEND works for ~10 min, then 80A1 | Keep-alive not sent; intermediate switch / firewall dropped idle socket | Send a small ZPL heartbeat every 60 s, or shorten the switch idle timeout. |
| TSEND = 80A1 after firmware update to V3.3 | Library revision mismatch – new FB65 expects UDT 65 v2 with extra fields | Recompile the UDT and re-initialise the instance DB. |
| 80A1 only when CPU is in F-STOP | Fail-safe logic is in the way of OB1; open-TCP blocks are skipped | Move the TSEND trigger to a non-F DB or use a CP for open-TCP and keep the F-CPU path pure. |
80A1 with REM_PORT := 0
|
Wildcard port – Zebra is fine, but some printers ignore it | Set REM_PORT := 9100 explicitly. |
Zebra ZM400 Specific Notes
- Port 9100 is the ZPL raw socket. ZM400 firmware revisions older than V53.16.5Z do not close the socket when a print job finishes, which is the desired behaviour for an S7 print trigger – the CPU keeps one long-lived socket and writes multiple ZPL commands into it.
- The Zebra replies with short status strings on the same socket (e.g.
ERROR 1234). Use theFB64 TRECVcall in OB1 to drain these into a receive DB and parse them in the user program. ATRECVerror 80A7 with a healthyTSENDmeans the printer reset the socket – almost always a malformed ZPL string. - If multiple printers are on the line, assign each a unique remote port (9100, 9101, 9102 …) and a unique connection ID. The 315F-2 PN/DP supports up to 8 active TCP connections on firmware V3.2.
Safety (F-CPU) Considerations
The CPU 315F-2 PN/DP is fail-safe. Open TCP communication via FB63–FB66 is a standard user-program function and is not safety-related. The F-runtime will not interfere with it as long as the F-shutdown is not asserted. If the F-CPU goes to F-STOP, OB1 stops executing and TSEND will not be called. This is the correct behaviour – a printer must never be the arbiter of a safety function. The 80A1 that appears in F-STOP is expected and does not need to be cleared; clear it by leaving F-STOP.
Commissioning Checklist
- CPU firmware V3.2.x confirmed (online → Module Information → Firmware).
- PROFINET X2 IP and subnet correct, gateway left blank for direct link.
- Routing disabled for the open-TCP subnet, or verified non-conflicting.
- FB65 TCON called in OB100 and OB101.
- UDT 65 fields:
ConnectionType = 17,LocalDeviceId = 2,ActiveEstablished = TRUE,RemoteAddress[5..6] = 0x23, 0x88(port 9100). - Local port 2500 (or any port in 2000–5000 not used by S7 / HTTP / PROFINET services).
- Cold restart performed after program download.
- TCON STATUS = 0000, DONE = TRUE within 2 s of RUN.
- Test ZPL string prints, Zebra log shows the job.
- TRECV in OB1 drains printer status replies into a receive DB.
What does TSEND status 80A1 mean on a 315F-2 PN/DP?
Status 80A1 means the TCP connection that TSEND is referencing is not yet established (or has been torn down). The open-TCP stack of the integrated PROFINET interface has not been told to set up the connection, so TSEND has nothing to send through. It is an application-layer error, not a cable or IP-stack error – ping will still work.
Is local port 2500 valid for the 315F-2 PN/DP firmware V3.2?
Yes. Port 2500 is inside the recommended 2000–5000 advisory range and is not reserved by the integrated S7, HTTP, or PROFINET services. Older firmware revisions (V2.x) would reject it; V3.0 and later accept it. Keep it inside 2000–5000 for safety.
Why is a CPU cold restart required for TCON to work?
The integrated PROFINET stack of the 315F-2 PN/DP only publishes its open-TCP connection table during the OB100 cold-restart path. If TCON is called only in OB1 of the first scan, it can hit a not-yet-published table and return 80A1. Placing TCON in OB100 and performing an Online > CPU Operating Mode > Cold Restart guarantees the table is up before the first OB1 cycle.
Can the integrated PROFINET port carry both PROFINET IO and open TCP at the same time?
What is the correct remote port for a Zebra ZM400?
Port 9100 – the Zebra raw-socket / line-printer daemon port. Some firmware revisions also expose 9101–9103 for additional print channels. Always set REM_PORT := 9100 explicitly; do not use 0 (wildcard) because the ZM400 can interpret it as an unknown service and reset the socket, surfacing as TSEND 80A1.
Do I need to call TCON every OB1 cycle?
Yes, until TCON reports DONE = TRUE. TCON is a job-controlled block; calling it with REQ = TRUE and a CONNECT parameter block is harmless and idempotent once the socket is up. The pattern is: hold REQ high in OB1, only start calling TSEND when DONE = TRUE. This is the same approach Siemens documents for the open-TCP programming guideline for S7-300/400.
What is the difference between FB65 TCON and FB65 TCON on S7-1500?
On S7-300/400 firmware V3.x, TCON is FB65 and its CONNECT block is type UDT 65 "TCON_PAR". On S7-1500, TCON is an instruction (not an FB) and the CONNECT block is a system data type of the same name but with additional fields (e.g. LocalInterfaceId for sub-interface selection). Porting the project to an S7-1500 means re-declaring the CONNECT block; the port numbers and connection IDs remain valid. Refer to the STEP 7 communication block reference for the version-specific differences.