S7-1200 Modbus TCP Gateway: Accessing RS485 Slaves via MB_CLIENT

David Krause10 min read
S7-1200SiemensTutorial / How-to
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

Overview

When an S7-1200 CPU (such as the S7-1214C DC/DC/DC or DC/DC/Rly) is connected to a Modbus TCP gateway that terminates an RS485 multidrop bus, the PLC cannot simply poll the gateway's own register map and expect to see the downstream field devices. The gateway only acts as a transport relay. To reach the slaves on the serial side, the MB_CLIENT instruction must be parameterized with the slave's Modbus Unit ID (also known as the slave address or station address). This article walks through the exact configuration in TIA Portal V15.1 and later, the relevant instance-DB parameters, the alternative TCON/TSEND/TRECV path for non-Joshua/Elpro gateways, and the verification steps that confirm end-to-end register access.

The reference architecture addressed here is:

  • S7-1214C CPU firmware V4.2 or later (MB_CLIENT ships in the S7-1200 base instruction library from V4.0 onwards)
  • Modbus TCP-to-RS485 gateway (e.g., Elpro 105U, Moxa MGate MB3170, HMS Anybus, Phoenix Contact EW50, or a generic "transparent" gateway)
  • One or more RS485 slaves (Modbus RTU) with station addresses 1–247
  • Default Modbus TCP port 502

Prerequisites

Confirm the following before you start configuring the PLC project:

  1. CPU firmware and library: The S7-1200 must be firmware V4.0 or higher to expose MB_CLIENT in the standard instruction palette. Open TIA Portal, select the device, and verify the firmware under Online > Diagnostics > Module Information.
  2. License-free instruction: MB_CLIENT (FB 1083) and MB_SERVER (FB 1084) are part of the S7-1200 base library and require no additional license, but the CPU must support Modbus TCP communication (any standard S7-121x/15x/15xC does).
  3. Gateway in transparent/unit-ID passthrough mode: The gateway must be configured to forward Modbus TCP requests to the serial bus using the embedded Unit ID as the RTU slave address. Most modern gateways expose this as a setting labeled Unit ID forwarding, Slave ID pass-through, or Transparent mode. If the gateway strips or replaces the Unit ID, the S7-1200 will only ever reach whatever slave address the gateway assigns by default.
  4. Ethernet connectivity: PLC, gateway, and engineering PC all on the same subnet (e.g., 192.168.0.0/24). The PLC's PROFINET interface must be assigned a fixed IP, not obtained from the router.
  5. TCP port 502 open: Confirm no firewall blocks port 502 between PLC and gateway.
  6. RS485 bus terminated and biased: 120 Ω termination at both ends, fail-safe bias resistors if the slaves are not internally biased.
Note: A Modbus gateway differs from a Modbus converter. A converter typically exposes the serial slaves as individual Modbus TCP nodes with their own IPs; a gateway keeps a single IP and demultiplexes requests by Unit ID. MB_CLIENT only works directly with a converter. To talk through a gateway, MB_CLIENT is still usable, but you must set MB_Unit_ID.

How MB_CLIENT Routes Requests Through a Gateway

The MB_CLIENT instruction builds a standard Modbus TCP ADU (Application Data Unit) consisting of:

  1. MBAP header (7 bytes): Transaction ID, Protocol ID (0x0000 for Modbus), Length, Unit ID.
  2. PDU (up to 253 bytes): Function code and payload.

The MBAP header's Unit Identifier byte is the field that tells the gateway which downstream serial slave to address. By default, TIA Portal sets this byte to 255 (0xFF) for the default Modbus TCP behavior. When a gateway is in the path, that byte must be overwritten with the RTU slave address you want to reach (1–247).

MBAP Field Length Default in MB_CLIENT Value Needed for Gateway
Transaction ID 2 bytes auto-incremented auto
Protocol ID 2 bytes 0x0000 0x0000
Length 2 bytes auto auto
Unit ID 1 byte 255 (0xFF) Slave address, e.g., 5

Step-by-Step Configuration in TIA Portal

Step 1 - Add MB_CLIENT to the Program

Open the S7-1200 program block (e.g., Main [OB1]) and drag Instructions > Communication > Modbus TCP > MB_CLIENT into a network. The first time you place it, TIA Portal automatically generates an instance data block (e.g., MB_CLIENT_DB) where the connection parameters are stored.

Step 2 - Configure the Connection Parameters

Open the instance DB and populate the following static tags. These are the values that define the gateway connection:

Parameter Type Example Value Description
Connect BOOL TRUE Trigger to (re)establish TCP connection
IP1..IP4 USINT[4] 192, 168, 0, 10 Gateway IPv4 octets (PLC sends to this IP)
Port UINT 502 Modbus TCP port on the gateway
MB_Unit_ID BYTE 5 RTU slave address on the RS485 bus
Mode USINT 0 = TCP Communication mode (TCP/IP)
DataPtr VARIANT P#DB20.DBX0.0 BYTE 100 Pointer to the data buffer in a global DB
DataLen UINT 100 Length of the data buffer in bits/words (function-code dependent)
Function USINT 3 (Read Holding) or 16 (Write Multiple) Modbus function code

Step 3 - Set MB_Unit_ID to the Serial Slave Address

This is the critical parameter. Most engineers miss it because TIA Portal's default wizard places 255 in MB_Unit_ID, which is the broadcast value for Modbus TCP/IP-direct devices. For a gateway scenario, you must hard-code the Unit ID to the slave's RTU station address:

Example ladder snippet in STL/structured text to set the Unit ID dynamically for two slaves polled alternately:

// Slave 5 - read 10 holding registers
IF "poll_cycle" = 0 THEN
    "MB_CLIENT_DB".MB_Unit_ID := 5;          // RTU slave address
    "MB_CLIENT_DB".Function   := 3;           // Read Holding Registers
    "MB_CLIENT_DB".DataPtr    := P#"DB_SlaveData".Slave5 BYTE 20;
    "MB_CLIENT_DB".DataLen    := 10;
    "MB_CLIENT_DB".REQ        := TRUE;
END_IF;

// Slave 12 - read 10 holding registers
IF "poll_cycle" = 1 THEN
    "MB_CLIENT_DB".MB_Unit_ID := 12;
    "MB_CLIENT_DB".Function   := 3;
    "MB_CLIENT_DB".DataPtr    := P#"DB_SlaveData".Slave12 BYTE 20;
    "MB_CLIENT_DB".DataLen    := 10;
    "MB_CLIENT_DB".REQ        := TRUE;
END_IF;

Step 4 - Compile, Download, and Go Online

  1. Compile the project (Project tree > S7-1200 station > Compile > Software).
  2. Download to the CPU (Online > Download to device).
  3. Go online and open the instance DB in monitor mode.

Step 5 - Verify with a Read Request

Trigger REQ once and observe the output parameters:

Status Tag Expected Value if OK Meaning
DONE TRUE (one cycle) Request completed without error
BUSY FALSE Not currently executing
ERROR FALSE No error detected
STATUS 0 0 = no error; 16#7001/7002 = in progress

Alternative Path: TCON, TSEND, TRECV for "Dumb" Gateways

If your gateway does not honor the MBAP Unit ID byte (some legacy or lower-cost units strip it and only forward to a fixed slave address), MB_CLIENT alone will not work. In that case you must construct the Modbus TCP frame manually using the Open User Communication (OUC) instructions:

Instruction Purpose
TCON Establish/configure TCP connection (FB 186)
TSEND Send the constructed Modbus ADU (FB 187)
TRECV Receive the response ADU (FB 188)
TDISCON Tear down the connection (FB 189)

A minimal Modbus TCP read-holding-registers request for slave 5, starting at register 0, length 10 would look like this when constructed in a byte buffer:

// Modbus TCP ADU for FC 03, slave 5, addr 0, qty 10
// Bytes 0..6 = MBAP header, bytes 7..12 = PDU

gw_request[0]  := 16#00;   // Transaction ID high (any unique)
gw_request[1]  := 16#01;   // Transaction ID low
gw_request[2]  := 16#00;   // Protocol ID high
gw_request[3]  := 16#00;   // Protocol ID low
gw_request[4]  := 16#00;   // Length high
gw_request[5]  := 16#06;   // Length low (6 bytes follow)
gw_request[6]  := 16#05;   // Unit ID = slave 5
gw_request[7]  := 16#03;   // Function code 03 (Read Holding Regs)
gw_request[8]  := 16#00;   // Starting address high
gw_request[9]  := 16#00;   // Starting address low
gw_request[10] := 16#00;   // Quantity high
gw_request[11] := 16#0A;   // Quantity low (10)

Then feed that buffer to TSEND and parse the response in TRECV. This is significantly more work than MB_CLIENT and is only recommended when the gateway cannot be reconfigured for Unit ID passthrough.

Why SCADA/HMI Worked but MB_CLIENT Did Not

Commercial SCADA packages such as Wonderware InTouch/AVEVA and Weintek cMT HMI have native Modbus drivers that expose a IP:Port:UnitID addressing scheme in the channel configuration (e.g., 192.168.0.10:502:5). The driver builds the ADU with the Unit ID byte set to 5 from the channel definition. MB_CLIENT, by contrast, hard-codes the Unit ID in the instance DB and uses its own connection-management logic. The two systems are not magically different on the wire; the HMI simply makes the Unit ID visible in a way the TIA Portal MB_CLIENT wizard does not.

Tool Where Unit ID is set Default
MB_CLIENT instance DB Static tag MB_Unit_ID 255
Wonderware Modbus TCP driver Channel property "Unit ID" 1
Weintek cMT Modbus gateway Device address suffix 1
Modscan32 / Modbus Poll Connection dialog "Unit ID" 1

Polling Multiple Slaves Through One Gateway

The S7-1200 only allows a limited number of concurrent MB_CLIENT connections (CPU-dependent: S7-1214C supports up to 8 active Modbus TCP connections; S7-1215C supports up to 16). To poll many slaves, you typically:

  1. Use a single MB_CLIENT instance and rotate MB_Unit_ID, DataPtr, and Function in a cyclic OB (e.g., OB35 at 100 ms) or in a state machine in OB1.
  2. Maintain a per-slave status word in a global DB so the HMI can see whether each slave is currently responding.
  3. Respect Modbus RTU turnaround timing: a typical request/response over RS485 at 9600 baud with 10 registers takes 30–80 ms. Cycle the poll list no faster than the worst-case slave.

Troubleshooting Matrix

Symptom Likely Root Cause Remedy
STATUS = 16#80C8 "No response from the partner" Gateway not reachable on IP/port Ping gateway, verify port 502, check firewall
STATUS = 16#80C9 "Connection lost" Gateway rebooted or cable unplugged Cycle Connect input to re-establish
STATUS = 16#80D2 "Modbus exception from slave" Slave received request but rejected it (illegal address, etc.) Check Slave_Status_Ex for exception code, verify register map
All requests time out but Connect=TRUE Gateway in server-only mode, not forwarding Unit ID Enable Unit ID pass-through in gateway config
PLC reads its own gateway only, not downstream MB_Unit_ID still 255 Set MB_Unit_ID to the RTU slave address (1–247)
Intermittent failures with CRC errors RS485 wiring / termination issue Add 120 Ω terminators, check shield grounding, lower baud
Reads return zeros, no error Wrong starting address or function code Verify register map; many RTU devices use 1-based addressing

Verification Checklist

  1. In TIA Portal's online watch table, force REQ to TRUE for one cycle and confirm DONE=TRUE, ERROR=FALSE, STATUS=0.
  2. Inspect the data buffer in the target DB; values should match the slave's actual register contents (compare with a Modbus scanner on a laptop).
  3. Toggle the slave's physical output by writing to a coil with FC 05/15 and observe the change in the field.
  4. From a PC, run Wireshark on the PLC switch port and confirm MBAP Unit ID matches the configured MB_Unit_ID.
  5. Disconnect the RS485 bus; the next request should return a Modbus exception or timeout, not a stale success.

Field-Proven Tips

  • Keep MB_Unit_ID in a single global DB tag and write it before setting REQ; some engineers have chased phantom bugs for hours because REQ was fired before the Unit ID was updated.
  • If the slave list is dynamic, store it in a UDT array (slave IP, Unit ID, register range) and iterate over it in OB35.
  • For deterministic bus traffic, place the MB_CLIENT call in a cyclic interrupt OB (OB30–OB38) rather than OB1 to avoid jitter from the main scan.
  • Document the gateway's Unit ID pass-through setting in the project HMI tag comments so the next commissioning engineer does not toggle it off.

Why can my SCADA reach the slaves through the gateway but MB_CLIENT cannot?

SCADA drivers let you specify the Unit ID directly in the channel (e.g., 192.168.0.10:502:5). MB_CLIENT hides the Unit ID inside the instance DB and defaults it to 255. Change the MB_Unit_ID static tag in the MB_CLIENT instance DB to the RTU slave address (1–247) to match what your SCADA is sending.

Do I need TCON/TSEND/TRECV or can I stay with MB_CLIENT?

Use MB_CLIENT whenever the gateway passes the MBAP Unit ID byte through to the serial bus transparently. Switch to TCON/TSEND/TRECV only when the gateway strips or rewrites the Unit ID, because MB_CLIENT has no way to bypass that behavior.

How many slaves can I poll through one MB_CLIENT instance?

There is no hard slave limit; MB_CLIENT sends one request at a time. The practical limit is the connection budget of the CPU (8 connections on S7-1214C, 16 on S7-1215C) and the Modbus RTU turnaround time. Cycle the Unit ID and DataPtr in a cyclic OB to poll many slaves sequentially.

What is the default value of MB_Unit_ID and why does it not work for gateways?

The default is 255 (0xFF), which is the Modbus broadcast address and tells the gateway "route to the serial device at the gateway's own default address". For per-slave addressing you must set MB_Unit_ID to the actual RTU station address (1–247).

What is the difference between a Modbus gateway and a Modbus converter?

A converter gives every serial slave its own IP and MB_CLIENT can poll each one directly. A gateway keeps a single IP and demultiplexes by Unit ID; MB_CLIENT must set MB_Unit_ID to select which slave behind the gateway should answer.

Back to blog