How to Configure Modbus TCP on Siemens S7-1200 (TIA Portal Step-by-Step)

By | April 9, 2026

The Siemens S7-1200 has built-in Modbus TCP support. No additional communication modules are needed. The CPU handles Modbus TCP natively through its PROFINET Ethernet port.

You configure it using two instruction blocks in TIA Portal:

  • MB_SERVER — makes the S7-1200 act as a Modbus TCP server (slave). Other devices read and write its registers.
  • MB_CLIENT — makes the S7-1200 act as a Modbus TCP client (master). It polls other Modbus devices like energy meters, VFDs, and sensors.

A single S7-1200 can run both roles at the same time — serving data to SCADA while polling field devices.

Despite the simplicity, engineers regularly run into problems: connection IDs not configured, holding register data blocks not sized correctly, MB_CLIENT requests overlapping, or Modbus addresses not matching the device register map.

This guide walks through both configurations with real TIA Portal settings, parameter explanations, and troubleshooting.

1. Requirements

ItemMinimum Version
TIA PortalV13 SP2 or later (V16+ recommended)
S7-1200 CPUFirmware V4.0 or later
Communication moduleNot required — built into CPU
Max simultaneous connections8 (server) / depends on CPU for client

The Modbus TCP instructions (MB_CLIENT and MB_SERVER) are found in TIA Portal under:

Instructions → Communication → Others → MODBUS TCP

2. How Modbus TCP Works on the S7-1200

ModeInstructionPLC RolePortWhat Happens
ServerMB_SERVERSlave — listens for requests502 (default)External clients (SCADA, HMI, other PLCs) connect to the S7-1200 and read/write its holding registers
ClientMB_CLIENTMaster — sends requestsEphemeralThe S7-1200 connects to external Modbus devices (meters, VFDs, sensors) and reads/writes their registers

Both instructions must be called cyclically in OB1 (the main program). They are not one-shot calls — they run continuously every scan cycle.

3. Step-by-Step: Configure S7-1200 as Modbus TCP Server

Step 1. Create a Data Block for Holding Registers

Create a new Global Data Block (e.g., DB10 “MB_HoldingReg”).

Add an array:

NameData TypeComment
HoldRegArray [0..99] of Word100 holding registers

This array is the data that external Modbus clients will read and write. Holding register 0 in Modbus maps to HoldReg[0], register 1 maps to HoldReg[1], etc.

⚠️ Important: Disable “Optimized block access” on this DB. Right-click the DB → Properties → Attributes → uncheck “Optimized block access.” Modbus requires fixed byte offsets, which optimized access does not guarantee.

Step 2. Add MB_SERVER to OB1

Drag the MB_SERVER instruction into your OB1 network from the instruction palette.

TIA Portal will prompt you to create an instance data block. Accept the default (e.g., DB11 “MB_SERVER_DB”).

Step 3. Configure MB_SERVER Parameters

ParameterValueMeaning
DISCONNECTFALSEKeep connection open
CONNECT_ID1Unique connection identifier (1–8)
IP_PORT502TCP port to listen on
MB_HOLD_REGP#DB10.DBX0.0 WORD 100Pointer to the holding register data block

Step 4. Download and Test

Download the program to the PLC. Use a Modbus TCP client tool (ModbusPoll, QModMaster, or your SCADA system) to connect to the PLC’s IP address on port 502. Read holding registers starting at address 0.

If you write a value to register 5 from the client tool, it should appear in DB10.HoldReg[5] in TIA Portal’s online monitor.

4. MB_SERVER Parameters Explained

ParameterTypeDescription
DISCONNECTBoolTRUE = close the current connection. FALSE = normal operation.
CONNECT_IDUIntUnique ID for this server connection (1–8). Each simultaneous client needs a different CONNECT_ID.
IP_PORTUIntTCP port to listen on. Default: 502.
MB_HOLD_REGVariant / PointerPointer to the holding register area (data block + offset + length).
NDRBool (output)New Data Ready — TRUE for one scan after a client writes data.
DRBool (output)Data Read — TRUE for one scan after a client reads data.
ERRORBool (output)TRUE if an error occurred.
STATUSWord (output)Error code. See Siemens documentation for codes.

Handling Multiple Clients

To support multiple simultaneous Modbus TCP clients, you need one MB_SERVER call per client connection, each with a different CONNECT_ID but pointing to the same holding register data block.

Example: 3 SCADA clients connecting simultaneously → 3 MB_SERVER instances with CONNECT_ID = 1, 2, 3.

5. Mapping Holding Registers to PLC Data

The MB_HOLD_REG parameter defines which PLC data is exposed as Modbus holding registers.

Direct Mapping

Modbus Register AddressPLC LocationValue
0DB10.HoldReg[0]Motor speed setpoint
1DB10.HoldReg[1]Temperature reading
2DB10.HoldReg[2]Pressure reading
10DB10.HoldReg[10]Alarm status (bitmask)

Writing Process Data to Holding Registers

In your PLC program, copy process values into the holding register array so external clients can read them:

DB10.HoldReg[0] := INT_TO_WORD(MotorSpeed);
DB10.HoldReg[1] := INT_TO_WORD(Temperature * 10);  // Scale factor 0.1
DB10.HoldReg[2] := INT_TO_WORD(Pressure * 100);    // Scale factor 0.01

Reading Commands from Holding Registers

When a SCADA client writes a value to a holding register, your program reads it:

IF DB11.NDR THEN  // New data received from client
    SpeedSetpoint := WORD_TO_INT(DB10.HoldReg[50]);
END_IF;

6. Step-by-Step: Configure S7-1200 as Modbus TCP Client

Step 1. Create a Connection Data Block

Create a new Global DB (e.g., DB20 “MB_ConnParam”) with the TCON_IP_v4 structure:

FieldValueMeaning
InterfaceId64HW identifier of the PROFINET interface (check in device configuration)
ID5Connection ID (must be unique)
ConnectionType11TCP (always 11 for Modbus TCP)
ActiveEstablishedTRUEPLC initiates the connection
RemoteAddress.ADDR[1]192First octet of target IP
RemoteAddress.ADDR[2]168Second octet
RemoteAddress.ADDR[3]1Third octet
RemoteAddress.ADDR[4]100Fourth octet → 192.168.1.100
RemotePort502Target device Modbus port
LocalPort0Auto-assign (let PLC choose)

Step 2. Create a Data Block for Received Data

Create DB21 “MB_ClientData” with an array to store read values:

NameData Type
ReadDataArray [0..49] of Word

Step 3. Add MB_CLIENT to OB1

Drag MB_CLIENT from the instruction palette into OB1. Create the instance DB (e.g., DB22).

Step 4. Configure MB_CLIENT Parameters

ParameterValueMeaning
REQTrigger signal (pulse)TRUE for one scan to send the request
MB_MODE00 = read, 1 = write
MB_DATA_ADDR40001Modbus register address to read (1-based)
MB_DATA_LEN10Number of registers to read
CONNECTDB20Pointer to TCON_IP_v4 connection structure
MB_DATA_PTRP#DB21.DBX0.0 WORD 10Pointer to store received data

Step 5. Trigger the Request

The REQ input must be pulsed (TRUE for one scan) to send a Modbus request. Use a timer or a clock memory bit:

// Trigger MB_CLIENT every 1 second using Clock_1Hz
MB_CLIENT_Instance.REQ := Clock_1Hz;

Wait for DONE = TRUE before sending the next request.

7. MB_CLIENT Parameters Explained

ParameterTypeDescription
REQBoolRising edge triggers a Modbus request
DISCONNECTBoolTRUE = disconnect from server
MB_MODEUSInt0 = read, 1 = write, 2 = diagnostics
MB_DATA_ADDRUDIntModbus register address (1-based: 40001 = first holding register)
MB_DATA_LENUIntNumber of registers/coils to read or write
CONNECTTCON_IP_v4Connection structure with target IP, port, connection ID
MB_DATA_PTRVariant / PointerPointer to the data area for read/write
DONEBool (output)TRUE when request completed successfully
BUSYBool (output)TRUE while request is in progress
ERRORBool (output)TRUE if request failed
STATUSWord (output)Error code

MB_MODE Values

MB_MODEActionModbus Function Code
0Read holding registersFC 03
0Read input registers (if MB_DATA_ADDR starts at 30001)FC 04
0Read coils (if MB_DATA_ADDR starts at 1)FC 01
1Write holding registersFC 06 (single) / FC 16 (multiple)
1Write coils (if MB_DATA_ADDR starts at 1)FC 05 (single) / FC 15 (multiple)
2DiagnosticsFC 08

The function code is selected automatically based on MB_DATA_ADDR and MB_DATA_LEN. You do not choose FC 03 or FC 16 manually — TIA Portal determines this from the address range.

8. Reading Multiple Devices Sequentially

The S7-1200 can only process one MB_CLIENT request at a time per connection. You cannot send the next request until the current one finishes (DONE = TRUE or ERROR = TRUE).

The Problem

If you have 5 energy meters to poll, you cannot call MB_CLIENT 5 times simultaneously. They must be sequential.

The Solution: State Machine

Use a step counter to cycle through devices:

CASE Step OF
    0:  // Read Meter 1 - Voltage
        MB_CLIENT_Instance.REQ := TRUE;
        MB_CLIENT_Instance.MB_DATA_ADDR := 40001;
        MB_CLIENT_Instance.MB_DATA_LEN := 3;
        // Point CONNECT to Meter 1 connection DB
        IF MB_CLIENT_Instance.DONE THEN Step := 1; END_IF;
        
    1:  // Read Meter 1 - Power
        MB_CLIENT_Instance.REQ := TRUE;
        MB_CLIENT_Instance.MB_DATA_ADDR := 40010;
        MB_CLIENT_Instance.MB_DATA_LEN := 4;
        IF MB_CLIENT_Instance.DONE THEN Step := 2; END_IF;
        
    2:  // Read Meter 2 - Voltage
        // Change CONNECT to Meter 2 connection DB
        MB_CLIENT_Instance.REQ := TRUE;
        MB_CLIENT_Instance.MB_DATA_ADDR := 40001;
        MB_CLIENT_Instance.MB_DATA_LEN := 3;
        IF MB_CLIENT_Instance.DONE THEN Step := 3; END_IF;
        
    // ... continue for all devices
    
    5:  // Restart cycle
        Step := 0;
END_CASE;

Each step waits for DONE before moving to the next. This ensures only one request is active at any time.

9. Data Type Handling Between Modbus and S7

Modbus registers are 16-bit words. S7-1200 data types vary. You need to convert.

Modbus DataS7 Data TypeConversion
1 register (16-bit unsigned)Word / UIntDirect — no conversion needed
1 register (16-bit signed)IntWORD_TO_INT()
2 registers (32-bit float)RealCombine 2 words into DWord, then DWORD_TO_REAL()
2 registers (32-bit unsigned)DInt / UDIntCombine 2 words into DWord
Scaled value (×0.1)RealINT_TO_REAL(value) * 0.1

32-Bit Float Example

Energy meter register 40010–40011 contains a FLOAT32 active power value.

// Combine two 16-bit words into a 32-bit float
TempDWord := SHL(WORD_TO_DWORD(DB21.ReadData[10]), 16) 
             OR WORD_TO_DWORD(DB21.ReadData[11]);
ActivePower := DWORD_TO_REAL(TempDWord);

⚠️ Warning: Byte order varies by device. Some meters use big-endian (AB CD), others use word-swapped (CD AB). If the float value looks wrong, swap the two words. See: Modbus Register Map Explained

10. Connection Management and TCON_IP_v4

Every MB_CLIENT and MB_SERVER connection needs a TCON_IP_v4 structure. Key fields:

FieldDescriptionNotes
InterfaceIdHardware ID of the PROFINET portFind in Device Configuration → PROFINET interface → System constants
IDConnection IDMust be unique across all Modbus connections on this CPU (1–255)
ConnectionType11Always 11 for TCP
ActiveEstablishedTRUE = client (PLC initiates), FALSE = server (PLC listens)
RemoteAddress.ADDRTarget IP address (4 bytes)Only for client mode
RemotePort502Target device port
LocalPort0 for client (auto), 502 for server

Finding the InterfaceId

In TIA Portal: Device Configuration → click on the PROFINET port → Properties → System constants tab → look for “Local~PROFINET_interface_1” → note the constant value (often 64 or 100).

11. Common Errors and How to Fix Them

ErrorSTATUS CodeCauseFix
No connection0x80C8Target device not reachableCheck IP address, cable, and firewall. Ping the device.
Connection refused0x80C9Target device not listening on port 502Verify Modbus TCP is enabled on the target device.
Timeout0x80C7Device did not respond in timeIncrease timeout. Check if device is overloaded.
Parameter error0x8188Wrong data type or pointerVerify MB_HOLD_REG or MB_DATA_PTR pointer syntax. Disable optimized block access.
Duplicate connection ID0x80B2Two MB_CLIENT/SERVER instances use the same CONNECT_IDAssign unique IDs to every connection.
Invalid register addressException 02MB_DATA_ADDR does not exist on the target deviceCheck the device register map. Verify 1-based vs 0-based addressing.
Request overlapBUSY stays TRUENew REQ sent before previous request completedWait for DONE or ERROR before triggering the next request.

12. Testing Your Configuration

Step 1. Test Server Mode

  1. Download the program to the S7-1200.
  2. Open ModbusPoll or QModMaster on your PC.
  3. Connect to the PLC’s IP on port 502.
  4. Read holding registers starting at address 0.
  5. Write a value to register 5 and verify it appears in DB10 in TIA Portal’s online monitor.

Step 2. Test Client Mode

  1. Run a Modbus Slave simulator on your PC (e.g., ModRSsim2).
  2. Set the simulator to listen on port 502 with known register values.
  3. Download the MB_CLIENT program to the S7-1200.
  4. Trigger a read request.
  5. Verify received values match the simulator.

Step 3. Verify with Wireshark

Capture on port 502 using filter: tcp.port == 502

You should see:

  • TCP SYN → SYN-ACK → ACK (connection setup)
  • Modbus requests from the PLC (if client mode)
  • Modbus responses from the device
  • MBAP header with correct Transaction ID, Unit ID, and function code

💡 Tip: Use the free Modbus Frame Decoder Tool to decode any Modbus TCP frame captured in Wireshark.

Summary

The S7-1200 handles Modbus TCP natively — no extra hardware needed. The two instructions are:

  • MB_SERVER — exposes PLC data as holding registers for external clients (SCADA, HMI)
  • MB_CLIENT — polls external Modbus devices (meters, VFDs, sensors)

The key things to get right:

  • Disable “Optimized block access” on all Modbus data blocks
  • Use unique CONNECT_ID for every connection
  • Wait for DONE before sending the next MB_CLIENT request
  • Match MB_DATA_ADDR to the device register map (1-based addressing)
  • Handle byte order carefully for 32-bit float values
  • Test with simulator tools before connecting to real devices
Author: Zakaria El Intissar

I'm an automation and industrial computing engineer with 12 years of experience in power system automation, SCADA communication protocols, and electrical protection. I build tools and write guides for Modbus, DNP3, IEC 101/103/104, and IEC 61850 on ScadaProtocols.com to help engineers decode, analyze, and troubleshoot real industrial communication systems.

Leave a Reply

Your email address will not be published. Required fields are marked *