System Overview and Hardware Identification
This integration uses Modbus/TCP (an application layer profile registered with IANA on TCP/502 in 1996) to exchange process data between a Siemens SIMATIC S7-400 station and a Schneider Electric Modicon Premium TSX P57 3634M processor. The S7-400 is configured in STEP 7 V5.x (the S7-400 classic line is not engineered in TIA Portal); the Premium is configured in Unity Pro (legacy) or EcoStruxure Control Expert (current). Both controllers expose an Ethernet interface and speak Modbus/TCP on TCP port 502, which is the IANA-assigned port for the Modbus protocol (registered by Schneider Automation). The full protocol is defined by the Modbus Organization's "MODBUS MESSAGING ON TCP/IP IMPLEMENTATION GUIDE V1.0b" (2006).
The TSX P57 3634M "M" suffix is the critical identifier: it indicates that the embedded 10/100 Mbps Ethernet port supports Modbus/TCP natively, removing the need for an external TSX ETY 4103/5103 NOE module. Earlier Premium CPU variants ending in "34" without the M (e.g., TSX P57 1634, 2634) do not support Modbus/TCP on the embedded port and require an NOE module for industrial Ethernet connectivity. The complete TSX P57 catalog (P571634, P572634, P573634M, P574634M, P575634M) varies in program memory and execution speed, but the M-suffix is the only Ethernet/Modbus variant.
Hardware Bill of Materials
| Item | Article / Order Number | Function |
|---|---|---|
| CPU 414-3DP | 6ES7414-3EM05-0AB0 | S7-400 central processor; supports STEP 7 V5.5+; integrated PROFIBUS DP master; work memory 4 MB code, 4 MB data |
| CP 443-1 | 6GK7443-1EX30-0XE0 (current) or 6GK7443-1EX11-0XE0 (legacy) | Industrial Ethernet CP for S7-400; supports S7 communication, PROFINET IO, open TCP via TCON/TDIS/TSEND/TRCV; max 64 TCP connections |
| TSX P57 3634M | TSXP573634M | Modicon Premium processor with integrated 10/100 Ethernet supporting Modbus/TCP server and client; firmware V4.0+ for client (master) support |
| Modbus/TCP PN-CPU option package | 2XV9450-1MB00 | Siemens software package providing Modbus/TCP client and server FBs for S7-300/400 and ET 200S CPUs with PROFINET interface or CP 443-1; installs under STEP 7 V5.5+ |
Network Topology and IP Plan
Use a dedicated /24 subnet (192.168.10.0/24) with one unmanaged switch (Scalance XC-208 or equivalent). Modbus/TCP is an unauthenticated, non-encrypted protocol; do not route it over the corporate network without firewall restrictions. If the two stations must be on different subnets, configure a static route on the engineering PC and pin TCP/502 between the two specific IPs in the firewall ACL.
Modbus/TCP Protocol Stack and PDU Format
Modbus/TCP is defined by the Modbus Organization specification. The application layer PDU (Protocol Data Unit) is identical to serial Modbus (1 byte function code + N bytes data), but it is encapsulated in an MBAP (Modbus Application Protocol) header and transported over TCP/IP rather than RS-485. The TCP layer provides reliable ordered delivery, so Modbus/TCP does not include CRC/LRC fields (the TCP checksum suffices). The full payload on the wire is MBAP (7 bytes) + Function Code (1 byte) + Data (N bytes).
MBAP Header (7 bytes)
| Field | Size | Description | Example (hex) |
|---|---|---|---|
| Transaction ID | 2 bytes | Identifies the request/response pair; client sets, server echoes unchanged | 0x0001 |
| Protocol ID | 2 bytes | Always 0x0000 for Modbus; 0x0001 reserved for MODBUS+ | 0x0000 |
| Length | 2 bytes | Number of following bytes (Unit ID byte + PDU), i.e., size of the rest of the frame | 0x0006 |
| Unit ID | 1 byte | 0xFF for pure Modbus/TCP; 0x01-0xF7 for routing to a downstream serial slave | 0xFF |
Function Codes Used in This Integration
| Code | Function | Schneider Tag | Siemens Tag | Use Case |
|---|---|---|---|---|
| 0x01 (1) | Read Coils | %M (boolean) | A, M, DBX | Discrete outputs (8 bits per byte) |
| 0x02 (2) | Read Discrete Inputs | %I (boolean) | E, I, DBX | Status inputs |
| 0x03 (3) | Read Holding Registers | %MW (word) | DBW, MW | Analogue setpoints and process data |
| 0x04 (4) | Read Input Registers | %IW (word) | EW, IW, DBW | Analogue measurements |
| 0x05 (5) | Write Single Coil | %M (boolean) | A, M, DBX | Single bit write |
| 0x06 (6) | Write Single Register | %MW (word) | DBW, MW | Single word write |
| 0x0F (15) | Write Multiple Coils | %M (array) | DBX array | Block bit write (up to 1968 bits) |
| 0x10 (16) | Write Multiple Registers | %MW (array) | DBW array | Block word write (up to 123 registers) |
For S7-400 <-> TSX P57 3634M, the typical exchange uses function codes 0x03 (Read Holding Registers) and 0x10 (Write Multiple Registers). The Schneider %MW (memory word) area is exposed as Modbus Holding Registers; the Siemens DB (data block) area receives the data on the S7-400 side.
Modbus Exception Codes (response function code = 0x80 | original)
| Code | Name | Meaning |
|---|---|---|
| 0x01 | Illegal Function | Server does not support the function code |
| 0x02 | Illegal Data Address | Offset + length exceeds server's data area |
| 0x03 | Illegal Data Value | Value in request is structurally invalid |
| 0x04 | Slave Device Failure | Server internal error or CPU in STOP |
| 0x05 | Acknowledge | Deprecated; long-duration operation accepted |
| 0x06 | Slave Device Busy | Retry later; back off the polling cycle |
| 0x08 | Memory Parity Error | Server detected parity error in memory |
| 0x0A | Gateway Path Unavailable | Gateway overloaded or misconfigured |
| 0x0B | Gateway Target No Response | Downstream serial slave not responding |
Server/Client Topology Decision Matrix
Modbus/TCP uses a strict client-server (master-slave) model: the client initiates the TCP connection on port 502, the server listens and responds. Either side can be the server; the choice is driven by application logic, polling rate, and engineering effort. The general rule: server side has less application code but cannot initiate; client side drives the cycle.
| Criterion | Siemens S7-400 as Server | Schneider TSX P57 3634M as Server |
|---|---|---|
| Engineering effort | Moderate - one FB (MB_SERVER) instantiated in OB1, no polling logic needed | Low - enable Modbus server in Unity Pro, define data area, no code needed |
| Polling cycle determinism | Driven by the client (TSX P57 polls the S7-400 in a fixed cycle) | Driven by the client (S7-400 polls the TSX P57) |
| Data freshness | Client request triggers update of exposed DB; one transaction per cycle | Client request triggers update of exposed %MW; one transaction per cycle |
| Troubleshooting tools | Wireshark with tcp.port==502; S7 diagnostic buffer (limited Modbus visibility) | Unity Pro trace, OS Loader console, Modbus diagnostic LEDs on Premium rack |
| Data exposure security | DB content is read by any client on the LAN - no authentication | %MW content is read by any client on the LAN - no authentication |
| Connection count limits | CP 443-1 supports up to 64 TCP connections (split between S7, PG, OP, and open TCP) | TSX P57 3634M supports up to 32 simultaneous Modbus/TCP clients |
Siemens S7-400 / CP 443-1 Configuration
This section assumes the S7-400 is the Modbus/TCP server. The MB_SERVER FB (FB103 in Modbus/TCP PN-CPU V4) is instantiated in OB1 and processes incoming Modbus requests from the TSX P57 client. The underlying transport uses the TCON/TDIS/TSEND/TRCV open TCP blocks, which are configured in NetPro as a TCP connection.
Prerequisites
- STEP 7 V5.5 SP4 or later installed on the engineering PC (the Modbus/TCP PN-CPU V4 requires V5.5 minimum).
- Modbus/TCP PN-CPU option package (article 2XV9450-1MB00) installed; this adds FBs MB_CLIENT (FB102 in V4), MB_SERVER (FB103 in V4), and supporting UDTs to the STEP 7 library.
- CP 443-1 inserted in the STEP 7 hardware configuration with a valid IP address (192.168.10.1), subnet mask (255.255.255.0), and an Ethernet subnet attached.
- NetPro must be openable from the SIMATIC Manager; the CP 443-1's "Ethernet" entry is where the TCP connection is configured.
- License key for the option package transferred to the engineering PC (the package requires license activation; floating license via License Key USB or local license).
Hardware Configuration (HW Config)
- Open the S7 station in SIMATIC Manager and launch HW Config.
- Insert the CP 443-1 in the S7-400 rack. The order number 6GK7443-1EX30-0XE0 (current, 4-port switch) or legacy 6GK7443-1EX11-0XE0 (single port) is selectable from the HW catalog under SIMATIC 400 > CP-400 > Industrial Ethernet.
- Double-click the CP to open its properties. On the "General" tab, set the IP address (192.168.10.1) and subnet mask (255.255.255.0). On the "Ethernet" sub-tab, configure the MAC address if required (factory MAC is on the front panel sticker).
- Switch to the "Options" tab in the CP properties. Set "Connection mode" to "TCP/IP" (this enables open TCP for the Modbus/TCP PN-CPU FBs to use). Enable "Keep-Alive" with an interval of 30 seconds for the Modbus/TCP server case to detect dead connections.
- Compile and download the hardware configuration. After download, cycle the CP 443-1 (or perform an S7-400 STOP -> RUN) to activate the new IP.
NetPro Connection Configuration
- Open NetPro from SIMATIC Manager (target system menu, or icon in toolbar).
- Right-click the CP 443-1 in the S7-400 station and select "Insert New Connection".
- Select "TCP connection" as the connection type (under "Other stations" or "Unspecified").
- For the partner (TSX P57 3634M), select "Unspecified" because the Schneider is not a Siemens partner and you do not have a partner's connection configuration to import. The connection ID is assigned automatically (e.g., ID = 1).
- In the connection properties, set the "Partner address" to 192.168.10.2 (the TSX P57 IP) and the "Partner port" to 502 (the IANA-registered Modbus port). The "Local port" can be left as the default (2000 / 2001) - the open TCP transport uses this for the underlying socket.
- Set "Active connection establishment" to "No" (the S7-400 server does NOT initiate - the Schneider client initiates the connection). This is mandatory for a server role.
- Compile and download NetPro to the CPU. Verify the connection appears in the S7-400 online connection diagnostics (target system > connection status).
Modbus/TCP PN-CPU FB Instantiation (S7-400 as Server)
- Open the S7 program in the project and open OB1.
- Open the STEP 7 library "Modbus_TCP_PN_CPU" (installed by the option package; default path: Programs > Modbus_TCP_PN_CPU) and drag MB_SERVER (FB103) into the project.
- Declare an instance DB: e.g., DB200 "iDB_MB_Server" with FB103 as its type.
- Wire the FB inputs in OB1 as shown in the code example below. Call MB_SERVER unconditionally in OB1; it manages its own state machine internally.
- Create a data block DB100 "DB_ModbusData" with a STRUCT containing an ARRAY[0..99] OF WORD. This DB holds the 100 Holding Registers exposed to the Modbus client.
- Download the program. The S7-400 will listen on TCP/502 once the CPU is in RUN and OB1 is executed.
Schneider TSX P57 3634M Premium Configuration
This section configures the TSX P57 3634M as the Modbus/TCP client (master) reading data from the S7-400 server. If the Schneider is the server, only the data exposure steps in the "Modbus Server" subsection apply.
Prerequisites
- Unity Pro XL (V8.0 or later) or EcoStruxure Control Expert (V14.0+) installed.
- TSX P57 3634M firmware version 4.0 or later for full Modbus/TCP client (master) support. Earlier firmware (V3.x) supports only server mode and requires an external NOE module for client role.
- The processor's embedded Ethernet port is enabled in the project and licensed.
- The MAST task of the TSX P57 is the location for the READ_VAR / WRITE_VAR calls. The FAST task is not suitable (can starve the OS Loader and cause Modbus timeouts).
Ethernet Port Configuration
- Open the TSX P57 station in Unity Pro.
- In the Project Browser, expand "Configuration" > "0: PLC Bus" > right-click the Ethernet port (e.g., "ETH_PORT_1") and select "Properties".
- Set the IP address to 192.168.10.2 and subnet mask to 255.255.255.0. Disable DHCP if static addressing is required (recommended for industrial networks).
- On the "Modbus TCP/IP" tab, enable "Modbus Server" (always available) and "Modbus Master" (firmware dependent - requires V4.0+).
- Configure "Number of simultaneous connections" for Modbus Master (default 16 is sufficient for most integrations).
- On the "Security" tab, disable any default firewall rules that would block inbound TCP/502; Modbus requires bidirectional traffic.
- Build the project and transfer to the TSX P57. The ETH LED on the front of the TSX P57 should turn solid green when the link is up.
Modbus Client (Master) Configuration with READ_VAR
- Create a new section in the MAST task of the TSX P57 program (e.g., Section "Modbus_Client").
- Declare a Derived Data Type (DDT) named "t_Modbus_Mgmt" with the structure shown in the code example below.
- Declare an instance variable:
iModbus : t_Modbus_Mgmt; - Call READ_VAR in the MAST section to read 20 words starting at Modbus address 100 of the S7-400 server. The OBJ parameter uses 1-based Schneider convention; 'OBJ' = '%MW100' means Holding Register 40100 in the Modbus addressing space.
- Trigger the read cyclically (e.g., every 100 ms) using a timer or %S6 (1-second system clock) divided by 10.
- Use WRITE_VAR to send data back to the S7-400. WRITE_VAR with NB = 0 is not valid; use NB >= 1.
Modbus Server (Slave) Data Exposure
If the TSX P57 3634M is acting as a server (alternative topology), the data is exposed automatically when the Modbus server is enabled in the Ethernet port configuration. The data is accessible as Modbus Holding Registers starting at address 40001, which maps to the first %MW word in the configured range. No application code is required for server mode.
- In Unity Pro, right-click the Ethernet port and select "Modbus Server Properties".
- Define the "Base Address" of the %MW area (default 0, meaning %MW0 = Modbus address 40001).
- Define the "Number of words" exposed (e.g., 100 words = Modbus address 40001 to 40100, mapping to %MW0..%MW99).
- Click "Apply" and download the configuration to the TSX P57.
Register and Tag Mapping Between Platforms
| Modbus Address (1-based, user) | Modbus Address (0-based, protocol) | TSX P57 3634M Tag | S7-400 Tag (MB_SERVER exposure) |
|---|---|---|---|
| 40001 | 0 | %MW0 | DB100.DBW0 |
| 40002 | 1 | %MW1 | DB100.DBW2 |
| 40050 | 49 | %MW49 | DB100.DBW98 |
| 40100 | 99 | %MW99 | DB100.DBW198 |
| 40200 | 199 | %MW199 | DB100.DBW398 |
The mapping is bidirectional: writing Holding Register 40001 from the client updates both the TSX P57 %MW0 (if TSX is the server) and the S7-400 DB100.DBW0 (if S7 is the server). Function code 0x10 (Write Multiple Registers) supports batch updates with a single transaction; this is the recommended write pattern to minimize TCP/502 traffic and improve cycle time. Coils (function codes 0x01/0x05/0x0F) pack 8 bits per byte; the Siemens side maps each coil to a single DBX bit, while the Schneider side maps each coil to a single %M bit.
Byte Order and Endianness
Modbus/TCP uses Big Endian (most significant byte first) for multi-byte values in the PDU. Both the S7-400 and the TSX P57 3634M store WORD values in Big Endian byte order internally, so the wire format matches the in-memory layout and no SWAP instruction is needed. For DWORD (32-bit) values transferred as two consecutive Holding Registers, the high word is transmitted first (Holding Register N) followed by the low word (Holding Register N+1). When constructing a DWORD in S7-400 from two DBWs, the S7-400's native DWord representation is also Big Endian, so DBW N becomes the high word and DBW N+1 the low word. On the TSX P57, %MD (memory double word) is also Big Endian and aligns directly with the Modbus/TCP wire format.
Code Examples for Both Platforms
Siemens S7-400 (STEP 7 V5.x) - MB_SERVER
The MB_SERVER FB runs in OB1 and processes incoming Modbus requests from the TSX P57 client. It uses the connection ID configured in NetPro and updates the local data block based on the Modbus function code and offset in the request. The FB is non-blocking; call it once per OB1 scan.
DATA_BLOCK DB 100
TITLE = Modbus Register Data
STRUCT
wHolding : ARRAY[0..99] OF WORD; // 100 Holding Registers (40001-40100)
END_STRUCT
END_DATA_BLOCK
FUNCTION_BLOCK FB 200
TITLE = Modbus TCP Server
VAR
iMB_Server : MB_SERVER; // FB103 from Modbus_TCP_PN_CPU library
bNDR : BOOL; // New data received (write command)
bDR : BOOL; // Data read complete (read command)
bError : BOOL; // Error flag
wStatus : WORD; // Error status word
END_VAR
BEGIN
iMB_Server(
ID := 1, // NetPro connection ID
MB_HOLD_REG:= 100, // DB number with Holding Registers
MB_HOLD_LEN:= 100, // Number of Holding Registers
MB_UNIT_ID := 255, // Unit ID (255 for Modbus/TCP)
MB_MODE := 1, // 1 = server mode
MB_DATA_PTR:= P#DB100.DBX0.0 WORD 100, // Pointer to local data area
NDR := bNDR, // New data flag
DR := bDR, // Read complete flag
ERROR := bError, // Error flag
STATUS := wStatus // Error status word
);
END_FUNCTION_BLOCK
ORGANIZATION_BLOCK OB 1
BEGIN
CALL FB 200, DB 200; // Instantiate MB_SERVER
END_ORGANIZATION_BLOCK
Siemens S7-400 (STEP 7 V5.x) - MB_CLIENT
If the S7-400 is the client, instantiate MB_CLIENT (FB102) and trigger it cyclically with a 100 ms timer. The MB_DATA_ADDR parameter is 0-based; to read Holding Register 40100, pass 99 (or pass 100 and subtract 1 in the application code).
FUNCTION_BLOCK FB 201
TITLE = Modbus TCP Client
VAR
iMB_Client : MB_CLIENT;
xTrigger : BOOL;
xDone : BOOL;
xBusy : BOOL;
xError : BOOL;
wStatus : WORD;
tCycle : TIMER; // 100 ms cycle timer
END_VAR
BEGIN
// 100 ms cyclic trigger
tCycle(IN := NOT tCycle.Q, PT := T#100MS);
IF tCycle.Q AND NOT xBusy THEN
iMB_Client(
REQ := TRUE,
ID := 1,
MB_MODE := 0, // 0 = Read
MB_DATA_ADDR:= 99, // 0-based: 99 = Holding Reg 40100
MB_DATA_LEN:= 20, // 20 words
DATA_PTR := P#DB200.DBX0.0 WORD 20, // Local buffer
DONE := xDone,
BUSY := xBusy,
ERROR := xError,
STATUS := wStatus
);
END_IF;
END_FUNCTION_BLOCK
Schneider TSX P57 3634M (Unity Pro) - READ_VAR / WRITE_VAR
TYPE t_Modbus_Mgmt :
STRUCT
nRetry : UINT; // Number of retries (3)
nTimeout : UINT; // Response timeout in seconds (2)
nActivity: UINT; // 0=Idle, 1=Read, 2=Write, 3=Error
nError : UINT; // 0=OK, 1=ComErr, 2=Inactive, 3=ModExc,
// 4=Len, 5=Tmo, 6=Refused, 7=BadAddr
abResult : ARRAY[0..19] OF WORD; // 20-word read buffer
END_STRUCT;
END_TYPE
PROGRAM Modbus_Client
VAR
iModbus : t_Modbus_Mgmt;
xReadBusy : BOOL;
xWriteBusy: BOOL;
iWriteBuf : ARRAY[0..9] OF WORD; // 10-word write buffer
END_VAR
// Read 20 words from S7-400 server every 100 ms
IF NOT xReadBusy THEN
iModbus.nActivity := 1;
READ_VAR(
ADR := '192.168.10.1', // S7-400 CP 443-1 IP
OBJ := '%MW100', // 1-based: 100 = Holding Reg 40100
NB := 20, // 20 words
MG := iModbus
);
xReadBusy := (iModbus.nError = 0);
// If nError <> 0, READ_VAR sets the flag itself; allow retry on next scan
IF iModbus.nError <> 0 THEN
xReadBusy := FALSE;
END_IF;
END_IF;
// Write 10 words to S7-400 server
IF NOT xWriteBusy THEN
iModbus.nActivity := 2;
WRITE_VAR(
ADR := '192.168.10.1',
OBJ := '%MW200', // Write to Holding Register 40201..40210
NB := 10,
EM := iModbus,
// Source data: iWriteBuf[0..9] populates registers 40201-40210
iWriteBuf[0] := 16#1234;
iWriteBuf[1] := 16#5678;
// ... populate remaining words
);
xWriteBusy := (iModbus.nError = 0);
IF iModbus.nError <> 0 THEN
xWriteBusy := FALSE;
END_IF;
END_IF;
Performance, Cycle Time, and Throughput
Modbus/TCP cycle time is dominated by three factors: TCP setup/teardown overhead, request-response round-trip latency, and application processing time. For a persistent connection (client keeps the TCP socket open and reuses it for multiple requests), the per-transaction overhead is ~5-15 ms on a 100 Mbps LAN. At a 100 ms polling cycle, the throughput is sufficient for ~10,000 words per second of process data.
| Parameter | Typical Value | Notes |
|---|---|---|
| Polling cycle | 50-500 ms | Faster than 50 ms risks overwhelming the S7-400's OB1 cycle |
| Words per transaction | 20-100 | Siemens MB_CLIENT limits to 100 words; Schneider READ_VAR allows up to 1000 but practical is ~100 |
| TCP setup time | 5-20 ms | Three-way handshake; TCP/502 SYN, SYN-ACK, ACK |
| Round-trip latency | 2-10 ms | 100 Mbps LAN with <10 switches |
| Application processing | 1-5 ms | Server-side MB_SERVER OB1 scan impact |
| Connection idle timeout | 30-300 s | CP 443-1 default is 30 s; TSX P57 default is 240 s |
For high-throughput integrations (more than 200 words per cycle), segment the data into multiple Modbus transactions of 100 words each, or upgrade to PROFINET or EtherNet/IP for a single tagged exchange. Modbus/TCP is a polling protocol; it does not support change-of-state notification or cyclic publish/subscribe semantics.
Step-by-Step Commissioning Procedure
- Verify the physical Ethernet link: link LEDs on the CP 443-1 and the TSX P57 3634M port should be solid green or amber. Use a continuity tester or the CP's diagnostic Web server (https://192.168.10.1) to confirm link up.
- Ping the S7-400 from the engineering PC:
ping 192.168.10.1should return <1 ms latency. If it fails, check VLAN configuration, IP routing, and physical cabling. - Ping the TSX P57 3634M:
ping 192.168.10.2. If it fails, verify the IP address via the OS Loader (e.g., Tera Term session on the TSX P57 console port at 19200 8-N-1) using theETH_INFOcommand. - On the engineering PC, run Wireshark with capture filter
tcp.port == 502 and ip.addr == 192.168.10.2to monitor Modbus traffic during commissioning. - Download the STEP 7 hardware configuration, NetPro connection table, and program (with MB_SERVER in OB1) to the S7-400. Verify the CPU is in RUN and the CP 443-1's ACT LED is solid green.
- Download the Unity Pro project (with READ_VAR logic in MAST) to the TSX P57 3634M. Verify the CPU is in RUN and the ETH LED is solid green.
- Observe the first Modbus request in Wireshark: the MBAP header should have Transaction ID = 0x0001, Protocol ID = 0x0000, Length = 0x0006, Unit ID = 0xFF, Function Code = 0x03, Starting Address = 0x0063 (99 decimal = 40100 1-based), Quantity = 0x0014 (20 words).
- Verify the S7-400's response: a successful read returns Function Code 0x03, Byte Count 0x28 (40 bytes = 20 words), and the 20 word values. An error returns Function Code 0x83 with an exception code byte.
- In Unity Pro, monitor the iModbus.nError value in a watch window. It should be 0 after each successful transaction. If non-zero, refer to the diagnostic table in the next section.
- Force a register write from the S7-400 side (using a VAT table to modify DB100.DBW0) and verify that the corresponding %MW0 on the TSX P57 updates within one polling cycle.
- Force a write from the TSX P57 (using an animation table to set %MW200) and verify the S7-400 DB100.DBW198 updates accordingly. This validates bidirectional data flow.
- Disconnect the Ethernet cable on the S7-400 side and verify the TSX P57 sets nError = 1 (communication error) within the timeout window (typically 2-3 s).
- Reconnect the cable and verify the connection re-establishes automatically (TSX P57 retry logic) and nError returns to 0 within one polling cycle.
Diagnostics, Status Codes, and Troubleshooting Matrix
Siemens MB_SERVER / MB_CLIENT STATUS Word
| STATUS (hex) | Meaning | Resolution |
|---|---|---|
| 0x0000 | No error | Normal operation |
| 0x0001-0x000F | Modbus exception code (illegal function, illegal address, etc.) from the remote server | Check the data area and register count on the server; verify the request offset is within the server's exposed range |
| 0x7000-0x7FFF | Modbus exception code (from MB_SERVER perspective, the local S7-400 returns this when the request is invalid) | Verify the request format and data pointer; check the data type of MB_DATA_PTR |
| 0x8085 | TCP connection error (partner not responding, wrong IP, firewall) | Ping test, verify partner port, check firewall ACL |
| 0x80A1 | Connection already established to the same partner | Check for duplicate FB instances or stale connections in NetPro |
| 0x80C8 | Connection timeout (no response from partner within timeout window) | Increase timeout, check partner CPU run state, verify partner has the Modbus FB active |
| 0x80D2 | TSAP or port invalid | Recheck NetPro connection settings; ensure the connection ID matches between NetPro and MB_SERVER |
| 0x80F7 | MBAP header invalid (corrupted TCP segment or wrong byte order) | Capture Wireshark trace; check for non-Modbus traffic on port 502; verify TCP MSS is not fragmenting the MBAP |
Schneider READ_VAR / WRITE_VAR Error Codes (nError field)
| Code | Meaning | Resolution |
|---|---|---|
| 0 | OK | Normal operation |
| 1 | Communication error (TCP RST, no response) | Check physical link, IP, firewall |
| 2 | Inactive server (port 502 not listening) | Verify MB_SERVER is instantiated in OB1; verify the CP 443-1 connection mode is TCP/IP |
| 3 | Modbus exception received | Check data area on server; verify offset + length fits in server's range |
| 4 | Inconsistent length (response shorter/longer than expected) | Verify NB (number of words) matches server register count; check for truncated TCP segment in Wireshark |
| 5 | Timeout (no response within nTimeout) | Increase nTimeout in the management structure; check partner CPU run state |
| 6 | Connection refused (TCP RST, e.g., wrong port) | Verify port 502 is open on the partner; check for partner firewall |
| 7 | Invalid address (ADR format wrong) | Check ADR string format 'a.b.c.d'; ensure no leading/trailing spaces |
Troubleshooting Matrix
| Symptom | Likely Cause | Resolution |
|---|---|---|
| No TCP SYN packets in Wireshark | TSX P57 not initiating; READ_VAR not in MAST scan; ADR IP wrong | Verify READ_VAR is called in MAST; check ADR string; verify TSX P57 MAST task is running |
| TCP SYN but no SYN-ACK | MB_SERVER not in OB1; S7-400 CPU in STOP; CP 443-1 not configured for TCP | Verify OB1 has MB_SERVER call; CPU RUN state; CP "Connection mode" = "TCP/IP" |
| TCP RST immediately after SYN | Partner IP wrong, or partner firewall blocks port 502 | Ping test; check ACL on managed switch; check Windows Firewall if S7 is in a VM |
| TCP connection OK but Modbus exception 0x02 (Illegal Data Address) | Register offset out of server's %MW or DB range | Reduce MB_DATA_ADDR + MB_DATA_LEN to fit server's data area; verify DB100 length in HW Config |
| Modbus exception 0x04 (Slave Device Failure) | Server CPU in STOP, or data pointer is a non-existent DB | Check CPU state on S7-400; verify DATA_PTR points to a valid DB; check for DB length mismatch |
| Intermittent timeouts every few hours | TCP keep-alive not set, or partner reaps idle connection | Enable keep-alive in CP 443-1 options; reduce polling cycle to keep connection active; or implement reconnect logic in MB_CLIENT |
| Wireshark shows correct requests, but iModbus.nError stays at 1 | TSX P57 Ethernet port not enabled for Modbus Master (firmware dependent) | Upgrade TSX P57 firmware to V4.0+; enable Modbus Master in port configuration |
| Successful exchange, but data appears swapped or doubled | Off-by-one between 0-based and 1-based addressing | Verify OBJ parameter uses 1-based on TSX P57; verify MB_DATA_ADDR uses 0-based on S7-400 |
| Successful exchange, but DB values are byte-swapped | Endian mismatch (rare for 16-bit, common for 32-bit) | Verify word storage; for 32-bit values, check that the high word is in the lower DBW offset |
Security Hardening and Migration Path
Modbus/TCP has no authentication and no encryption. Production deployments should implement the following hardening steps: (1) place the Modbus/TCP traffic on a dedicated VLAN with no routing to the corporate network; (2) configure the managed switch ACL to allow TCP/502 only between the two specific IP addresses; (3) disable ICMP echo on both controllers to prevent reconnaissance; (4) monitor TCP/502 traffic for anomalous polling patterns (rate-based IDS rules); (5) for sensitive applications, migrate to Modbus/TLS (introduced in the Modbus/TCP Security specification, 2018) or to OPC UA with certificate-based authentication.
The TSX P57 3634M is part of the Modicon Premium line, which Schneider Electric has discontinued (end of commercialization 2018, end of support 2024 for the Premium platform). The migration target is the Modicon M340 (BMXP342020) or Modicon M580 (BMEP582040) with the same Modbus/TCP port concept. The M580 BMEP58 CPU has an integrated Modbus/TCP server and client and uses the same READ_VAR/WRITE_VAR syntax as the Premium. The M340 also supports Modbus/TCP with a BMX NOE 0100/0110 Ethernet module or the integrated Ethernet on the BMX P34 20xx CPU variants. The same Modbus/TCP integration pattern applies to the Modicon M251 and M221 generation logic controllers used in smaller machine automation.
On the Siemens side, the S7-400 line is still supported (spare parts guarantee until 2030) but new designs use the S7-1500 with the integrated MODBUS_CLIENT and MODBUS_SERVER instructions in TIA Portal V14+ (no separate option package required). The S7-1500's data block mapping is identical: a DB of WORDs maps directly to Modbus Holding Registers. The transition from S7-400 to S7-1500 is largely a STEP 7 V5.x → TIA Portal conversion, and the application code (MB_SERVER/MB_CLIENT logic) maps cleanly to the new MODBUS_SERVER/MODBUS_CLIENT instruction blocks.
Frequently Asked Questions
Does the CP 443-1 support Modbus/TCP natively without the option package?
No. The CP 443-1 provides the open TCP transport layer, but the Modbus Application Protocol (MBAP) header parsing, function code dispatch, and exception handling are implemented by the FBs in the Modbus/TCP PN-CPU option package (article 2XV9450-1MB00). Without the package, you cannot exchange Modbus registers from STEP 7 V5.x. Reference: SIMATIC Modbus/TCP PN-CPU Function Manual (entry ID 109755501).
Which side should be the Modbus/TCP server, the S7-400 or the TSX P57 3634M?
Either side can be the server. The choice is driven by the application: if the Schneider controller is the process owner and cyclically reads process data from the S7-400, the S7-400 is the server. If the S7-400 is the process owner, the TSX P57 is the server. The server side requires less application code (one FB in OB1) but cannot initiate the connection; the client side initiates the TCP session and triggers the data exchange.
What is the maximum number of registers that can be read in a single Modbus/TCP transaction?
The Modbus standard allows up to 125 Holding Registers (function code 0x03) or 2008 Coils (function code 0x01) in a single request. In practice, the Siemens MB_CLIENT limits to 100 words per transaction; the Schneider READ_VAR allows up to 1000 words but practical cycle times drop above 100 words. For larger data sets, segment the request into multiple Modbus transactions or upgrade to PROFINET or EtherNet/IP for a single tagged exchange.
Why do I get exception 0x02 (Illegal Data Address) immediately after the first read succeeds?
The first read succeeds because the offset is valid; the subsequent read fails because the offset + length exceeds the server's data area. Verify that MB_DATA_ADDR + MB_DATA_LEN on the S7-400 side (or OBJ + NB on the TSX P57 side) does not exceed the server's exposed register count. For the S7-400 server, check that the DB size in MB_HOLD_LEN matches the requested length and that the DB has been downloaded to the CPU.
Can I route Modbus/TCP between the S7-400 and the TSX P57 3634M through a router?
Yes, but not recommended for production. Modbus/TCP is an unauthenticated, non-encrypted protocol on TCP/502; routing it over a wide-area network exposes the controllers to unauthorized polling. If routing is required, place a stateful firewall that allows TCP/502 between the two specific IPs only, and disable ICMP echo on the controllers to avoid reconnaissance. For sensitive applications, migrate to Modbus/TLS (introduced in the Modbus/TCP Security specification, 2018) or to OPC UA with certificate-based authentication.