S7-1200 Modbus RTU Master with CM 1241 RS485: Programming Guide
This field-reference covers configuring a SIMATIC S7-1200 CPU as a Modbus RTU master using a CM 1241 RS485 (or RS422/485) communication module, the Modbus_Comm_Load and Modbus_Master instruction blocks, and exposing the polled data to an HMI on TIA Portal. The workflow is identical whether the slave is a power meter, a VFD, a sensor, or a second S7-1200 acting as a slave; only the slave address, register map, baud rate, parity, and response timeout change.
1. Overview
Modbus RTU over RS-485 is the most common serial protocol used by low-voltage power devices (meters, soft starters, drives, trip units) and a long list of third-party sensors. The S7-1200 does not ship with native Modbus RTU master capability in its firmware: you must install the "SIMATIC S7-1200 Modbus Master RTU" library, place a CM 1241 (RS485 or RS422/485) module to the left of the CPU, and call Modbus_Comm_Load once per port and Modbus_Master for every request.
The S7-1200 acts as the Modbus master; the power device is a slave. The full Siemens entry on Modbus RTU between two S7-1200 CPUs (entry ID 47756141) uses the same library and provides a complete sample project for the master side. See Siemens Support Entry 47756141 - S7-1200 Modbus RTU Communication Example.
2. Prerequisites
2.1 Hardware
- S7-1200 CPU in the 12xxC family (CPU 1211C / 1212C / 1214C / 1215C / 1217C). Compact CPUs without a separate signal board slot require a CM 1241 to expose RS-485.
- CM 1241 RS485 / RS422 module. Common catalog numbers:
- 6ES7241-1CH30-1XB0 - CM 1241 RS485 (legacy)
- 6ES7241-1CH31-0XB0 - CM 1241 RS422/485 (current, supports Modbus RTU master and slave)
- 6ES7241-1CH32-0XB0 - CM 1241 RS232 (serial Modbus to RS-232 devices only)
- CM 1241 must be installed directly to the left of the CPU (slot 101) or chained off another CM/CP/SM using the S7-1200 internal bus.
- Termination: enable the terminating resistor on the CM 1241 if the device is at the physical end of the RS-485 trunk (DIP switch on the back of the module, 120 Ω between A and B).
2.2 Firmware
- CPU firmware V2.0 minimum for the original Modbus library; V4.0 or higher is required for library V4.0+ and is recommended for any new project.
- CM 1241 firmware: shipped at the latest revision when purchased new; flash with TIA Portal > Online > Accessible devices > Firmware update if a vendor driver requires it.
2.3 Software
- STEP 7 (TIA Portal) Basic or Professional, V13 SP1 or higher recommended. V10.5 is referenced in the original question and continues to work, but new installs should use V17 or V18.
- WinCC (TIA Portal) Basic or Comfort for the HMI project (Basic on the same TIA Portal instance as the PLC).
- Third-party: MODSCAN32 (WinTech) or any Modbus master test tool to validate the slave before involving the PLC.
2.4 Wiring (RS-485, 2-wire half-duplex)
| CM 1241 terminal | Signal | Slave A/B |
|---|---|---|
| 3 (T/R+, A) | Data + | A (or D+) |
| 8 (T/R-, B) | Data − | B (or D−) |
| 5 (GND) | Reference | Common / GND |
| 4 (RTS/CTS) | Not used in 2-wire RS-485 | n.c. |
Use a shielded twisted pair (Belden 3106A or equivalent), shield grounded at one end only. Daisy-chain the A and B lines; do not use a star topology. Maximum stub length is generally 30 m at 115.2 kbit/s, shorter for higher baud rates.
3. Configuring the Project and Hardware
- Create a new TIA Portal project and add the S7-1200 station.
- In Device configuration, drag a CM 1241 (RS422/485) onto slot 101 of the CPU.
- Open the CM 1241 properties:
- Port configuration > Operating mode: Half-duplex (RS485) 2-wire
- Baud rate: match the slave (9600 is the safe default for power meters)
- Parity: match the slave (Even is most common for Modbus RTU energy devices)
- Data bits / Stop bits: 8 / 1 (or 8 / 2 per slave spec)
- Flow control: None for RS-485
- Note the Hardware identifier of the CM 1241 (e.g.
269) from the System constants tab.Modbus_Comm_Loadneeds this value at itsPORTinput.
4. Installing the Modbus Master Library
- Right-click PLC_1 > External source files and choose Retrieve library elements.
- The library is shipped with TIA Portal: SIMATIC S7-1200 Modbus Master RTU. Locate it under Options > Global libraries > Modbus_Master_RTU.
- Drag the two FB types
Modbus_Comm_Load(FB 1080) andModbus_Master(FB 1081) into your project under Program blocks > Master copies or call them directly from the library folder. - Copy the matching DB instances into your program blocks; the library uses FB 1080/1081 with associated instance DBs.
5. Calling Modbus_Comm_Load (Run Once on Startup)
Modbus_Comm_Load configures the port and must be executed exactly once per CM 1241. Place the call in OB1, a startup OB, or a cyclic OB and trigger REQ with a one-shot on cold restart.
| Parameter | Type | Meaning | Typical value |
|---|---|---|---|
REQ |
BOOL | Start (rising edge) | FirstScan |
PORT |
WORD | Hardware identifier of CM 1241 | 269 (or 270 for slot 102) |
BAUD |
DWORD | Baud rate | 9600 |
PARITY |
WORD | 0=None, 1=Odd, 2=Even | 2 (Even) |
FLOW_CTRL |
WORD | 0=None, 1=Hardware (RS-232 only) | 0 |
RTS_ON_DLY |
WORD | RTS on delay (ms) | 0 |
RTS_OFF_DLY |
WORD | RTS off delay (ms) | 0 |
RESP_TO |
WORD | Slave response timeout (ms) | 1000 (raise for slow slaves) |
DONE |
BOOL | Configuration complete | Tag: MB_Load_Done
|
ERROR |
BOOL | Configuration error | Tag: MB_Load_Error
|
STATUS |
WORD | Error code (see Section 10) | Tag: MB_Load_Status
|
5.1 Sample SCL call
// OB1 - port initialisation (call once on cold restart)
IF "FirstScan" THEN
"MB_Comm_Load_DB"(REQ := TRUE,
PORT := 269, // CM 1241 hardware ID
BAUD := 9600,
PARITY := 2, // Even
FLOW_CTRL := 0, // None (RS485)
RTS_ON_DLY := 0,
RTS_OFF_DLY := 0,
RESP_TO := 1000,
DONE => "MB_Load_Done",
ERROR => "MB_Load_Error",
STATUS => "MB_Load_Status");
END_IF;
5.2 Sample ladder equivalent
Network 1: rising-edge coil on FirstScan drives the REQ input of the Modbus_Comm_Load box. Outputs DONE and ERROR are wired to tags; STATUS is wired to a WORD tag and animated on the HMI for diagnostics.
6. Calling Modbus_Master (One Per Slave or One Per Register Group)
Modbus_Master issues a single Modbus request per rising edge on REQ. The instruction is edge-triggered and must not be called again until DONE or ERROR becomes true. The typical pattern is to cycle through slaves inside a cyclic OB, gating each REQ on the previous call's completion.
| Parameter | Type | Meaning | Typical value |
|---|---|---|---|
REQ |
BOOL | Trigger (rising edge) | Polled flag |
MB_ADDR |
USINT / WORD | Modbus slave address 1-247 | 1 |
MODE |
WORD | 0=Read, 1=Write, 2=Read/Write, 3=Write/Read | 0 |
DATA_ADDR |
WORD | Modbus starting address (1-based, see slave manual) | 0 (function 03 holding register 40001) |
DATA_LEN |
WORD | Number of words or bits to transfer | 10 |
DATA_PTR |
VARIANT | Pointer to data block or tag array | P#DBxx.DBX0.0 BYTE 20 |
DONE |
BOOL | Request complete without error | Tag |
ERROR |
BOOL | Request failed | Tag |
STATUS |
WORD | Error code (see Section 10) | Tag |
DATA_ADDR uses the Modbus "register number minus one" convention. To read holding register 40001, set DATA_ADDR = 0. To read 40010, set DATA_ADDR = 9. For function code 04 (input registers) the address range starts at 30001, so register 30001 = DATA_ADDR 0.6.1 Cyclic polling pattern (SCL)
// OB1 - poll three power meters in sequence
CASE "PollStep" OF
0: // meter #1: 10 holding registers from 40001
"MB_Master_DB"(REQ := TRUE,
MB_ADDR := 1,
MODE := 0, // Read
DATA_ADDR := 0, // 40001
DATA_LEN := 10,
DATA_PTR := P#"Meter1_Reg".DBX0.0 BYTE 20,
DONE => "MB_Done",
ERROR => "MB_Error",
STATUS => "MB_Status");
IF "MB_Done" OR "MB_Error" THEN
"PollStep" := 1;
END_IF;
1: // meter #2: 6 holding registers from 40020
...
IF "MB_Done" OR "MB_Error" THEN
"PollStep" := 2;
END_IF;
2: // meter #3: 4 holding registers from 40100
...
IF "MB_Done" OR "MB_Error" THEN
"PollStep" := 0;
END_IF;
END_CASE;
7. Modbus Function Codes Supported by Modbus_Master
| Function code | Direction | DATA_ADDR base | DATA_LEN units | Typical use |
|---|---|---|---|---|
| 01 - Read Coils | Master → Slave | 0 (coil 1) | Bits (1-2000) | Digital outputs / status |
| 02 - Read Discrete Inputs | Master → Slave | 0 (input 10001) | Bits (1-2000) | Digital inputs |
| 03 - Read Holding Registers | Master → Slave | 0 (reg 40001) | Words (1-125) | Measured values, setpoints |
| 04 - Read Input Registers | Master → Slave | 0 (reg 30001) | Words (1-125) | Metering (V, I, kW, kWh) |
| 05 - Write Single Coil | Master → Slave | 0 (coil 1) | 1 bit | Trip / close commands |
| 06 - Write Single Register | Master → Slave | 0 (reg 40001) | 1 word | Setpoint write |
| 15 (0x0F) - Write Multiple Coils | Master → Slave | 0 | Bits (1-1968) | Bulk command |
| 16 (0x10) - Write Multiple Registers | Master → Slave | 0 | Words (1-123) | Bulk setpoint / time sync |
For "Read holding registers from address 40001, length 10" use MODE = 0, DATA_ADDR = 0, DATA_LEN = 10. The DATA_PTR must point to a buffer of 2 * DATA_LEN bytes.
8. Sample Program: Read a Power Meter and Display on HMI
8.1 Data block layout
DATA_BLOCK "PowerMeterData"
STRUCT
Voltage_L1_N : REAL; // 40001 (V, scale 0.1)
Voltage_L2_N : REAL; // 40003
Voltage_L3_N : REAL; // 40005
Current_L1 : REAL; // 40007 (A, scale 0.01)
Current_L2 : REAL; // 40009
Current_L3 : REAL; // 40011
ActivePower : REAL; // 40013 (W, scale 1)
Frequency : REAL; // 40015 (Hz, scale 0.01)
END_STRUCT;
END_DATA_BLOCK
8.2 Modbus read call (OB1, SCL)
// Read 8 holding registers (40001..40015 odd, 16 bytes)
"MB_Master_DB"(REQ := "MB_Trigger",
MB_ADDR := 1,
MODE := 0,
DATA_ADDR := 0, // 40001
DATA_LEN := 8, // 8 words = 16 bytes
DATA_PTR := P#"PowerMeterData_Raw".DBX0.0 BYTE 16,
DONE => "MB_Done",
ERROR => "MB_Error",
STATUS => "MB_Status");
8.3 Word-to-real scaling (SCL, FC "ScaleMeter")
// Convert raw INT to REAL with scaling
"PowerMeterData".Voltage_L1_N := INT_TO_REAL("PowerMeterData_Raw".Volts_L1) / 10.0;
"PowerMeterData".Current_L1 := INT_TO_REAL("PowerMeterData_Raw".Amps_L1) / 100.0;
"PowerMeterData".ActivePower := INT_TO_REAL("PowerMeterData_Raw".Watts_Tot);
"PowerMeterData".Frequency := INT_TO_REAL("PowerMeterData_Raw".Hz) / 100.0;
8.4 HMI tag wiring
Create HMI tags that point at the scaled values in PowerMeterData (e.g. PowerMeterData.Voltage_L1_N). Place a numeric output on the screen with format string 999.9 " V". Add a status bar driven by MB_Error and MB_Status to surface communication faults directly on the screen.
9. Verification Procedure
- Validate the slave first with MODSCAN32. Connect a USB-to-RS-485 converter to the bus, set the same baud, parity, and slave address, and read the registers the PLC will request. If MODSCAN returns valid data, the slave is wired and configured correctly. This step eliminates 80% of integration time per the original Siemens reply on the same thread.
-
Compile and download the TIA Portal project to the S7-1200. Watch
MB_Load_Donego TRUE in online watch table within one second of the first scan. -
Go online → Watch → force
MB_TriggerTRUE to issue a single read. VerifyMB_Donetransitions TRUE and the data blockPowerMeterData_Rawis populated. - Run the cyclic poller and confirm the data refreshes on the HMI at the expected rate. Power meters typically publish new data at 1 Hz; reading more frequently just repeats the last value.
- Bus diagnostics. Open the CM 1241 in online mode; under Diagnostics you can read Frame errors, Parity errors, and Overrun errors counters. A non-zero parity error count almost always means the slave and master parity settings disagree.
10. Troubleshooting Matrix
| STATUS (hex) | Meaning | Root cause | Fix |
|---|---|---|---|
| 0x0000 | No error | - | - |
| 0x80C8 | Response timeout | Slave not answering within RESP_TO; wrong address, wrong baud, A/B swapped, no common ground, terminating resistor missing on a long bus | Verify wiring polarity, lower baud, raise RESP_TO to 2000 ms for slow slaves |
| 0x80D1 | Parity or framing error from slave response | Parity / data bits / stop bits mismatch | Match CM 1241 port config to the slave spec sheet |
| 0x80D2 | CRC error | Electrical noise, missing termination, A/B reversed, wrong baud | Add 120 Ω at both ends, check shield grounding, swap A and B |
| 0x80D4 | Modbus exception from slave (function code returned with error bit set) | Slave does not support the requested address or function | Cross-check the slave register map; some devices split holding vs. input registers or require unlock codes |
| 0x80E0 | Read passed MB area end (DATA_ADDR + DATA_LEN > slave range) | Read length exceeds available registers | Reduce DATA_LEN to what the slave exposes |
| 0x80FF | Library / instance error | Wrong library version, mismatched FB/UDT, instance DB not regenerated after upgrade | Recompile all blocks; re-fetch the library matching CPU firmware |
| 0x8180 / 0x8181 | MB_Comm_Load parameter error | Invalid PORT ID, invalid BAUD, RESP_TO out of range | Confirm hardware ID from System constants; BAUD must be 300/600/1200/2400/4800/9600/19200/38400/57600/76800/115200; RESP_TO 5..65535 ms |
11. Performance and Timing Guidelines
- One transaction at a time per port. The CM 1241 cannot pipeline. If you have five slaves, sum the worst-case response times to compute the poll cycle.
-
Worst-case frame time at 9600/8/N/1 for a 10-word read is roughly:
frame = (3.5 chars silence) + (8 bytes header) + (10 words * 2) + (CRC 2) + (3.5 chars silence) = 35 bits start/idle + 80 + 200 + 16 + 35 = ~366 bits @ 9600 = ~38 ms per transaction - At 19200 baud, the same transaction is ~19 ms. Five slaves polled sequentially refresh every ~95-200 ms, which is well within a 100 ms HMI update rate.
- If the bus is large (> 20 devices) or runs at 115.2 kbit/s, consider splitting the bus across two CM 1241 modules in the same S7-1200 station.
12. Cross-References and Related Tasks
- For Modbus TCP (rather than RTU) on the S7-1200, the configuration differs: use the PROFINET port of the CPU and the
MB_CLIENT/MB_SERVERblocks. Siemens documents this in the S7-1200 manual collection at TIA Portal Documentation - Modbus TCP Examples. - For making the S7-1200 a Modbus RTU slave (e.g. an HMI acting as master), use the
Modbus_Slaveinstruction (FB 1082) in the same library. The CM 1241 port setup uses the sameModbus_Comm_Loadcall. - For wiring a CM 1241 RS-232 to a Modbus device that uses RS-232, switch
FLOW_CTRLto1(hardware) and wire RTS/CTS. RS-232 cable length is limited to ~15 m.
What library do I need for S7-1200 Modbus RTU master?
Use the "SIMATIC S7-1200 Modbus Master RTU" global library shipped with TIA Portal. It contains Modbus_Comm_Load (FB 1080) for port configuration and Modbus_Master (FB 1081) for issuing requests. Library V4.0+ requires CPU firmware V4.0 or higher; older library versions work on CPU firmware V2.0+.
How do I set the Modbus register address in DATA_ADDR?
Subtract one from the Modbus register number. To read holding register 40001 set DATA_ADDR = 0; for 40010 set DATA_ADDR = 9. The same rule applies to coils (00001 = 0) and input registers (30001 = 0). Confirm the register map in the slave's user manual before coding.
STATUS 0x80C8 means what and how do I fix it?
0x80C8 is a slave response timeout. The master sent a request but received no reply within RESP_TO (default 1000 ms). Common causes: wrong slave Modbus address, A and B wires swapped, missing common ground between master and slave, no 120 Ω termination at the bus ends, or baud rate mismatch. Increase RESP_TO to 2000 ms for slow slaves and verify with MODSCAN32 first.
Can I poll multiple Modbus slaves from one CM 1241?
Yes. One CM 1241 supports multiple slaves on the same RS-485 bus, but only one transaction at a time. Run Modbus_Comm_Load once, then call Modbus_Master sequentially with a different MB_ADDR per slave. Gate each call on the previous one's DONE or ERROR bit. For very large buses split the slaves across two CM 1241 modules.
Why does my HMI show 0 even though MB_Done is TRUE?
The DATA_PTR buffer receives raw 16-bit words, not scaled REAL values. You need a separate conversion step (e.g. INT_TO_REAL divided by the meter's scaling factor) to get engineering units, and the HMI tag must point at the scaled value, not the raw word. Also confirm the byte order: some power meters transmit little-endian, some big-endian; the CM 1241 returns bytes exactly as received, so byte-swap if the manual says so.