Overview: Modbus RTU on ET200SP S7-1500
The SIMATIC ET200SP distributed I/O system with an S7-1500 class CPU (including the compact CPU 1510SP, 1512SP, 1514SP, and 1515SP) can host Modbus RTU master or slave communication through a CM PtP (Point-to-Point) communication module plugged into the ET200SP baseUnit. The CM PtP module provides the RS-485 or RS-232 physical interface required for Modbus RTU on a 2-wire or 4-wire bus, and the Modbus protocol is implemented inside the CPU firmware as library blocks:
- Modbus_Comm_Load (FB 1078 / FB 1080 depending on firmware) — ports and parameterizes the CM PtP module for Modbus RTU mode.
- Modbus_Master (FB 1080) — implements an RTU master when the S7-1500 is the polling device.
- Modbus_Slave (FB 1081) — implements an RTU slave when the S7-1500 is the responder.
This article consolidates field-proven diagnostics for the three most disruptive error families encountered when commissioning Modbus RTU on an ET200SP:
- Runtime error codes
16#81E2and16#81E7returned by the Modbus master/slave blocks. - CPU stop with diagnostic buffer entry "Error in read access to the periphery (address I 0) in FB 613".
- Address-mapping confusion between S7 data-block offsets and the Modbus register model presented to the external master or slave device.
Hardware Prerequisites
Modbus RTU on ET200SP requires the following configuration. None of the blocks will work without every item below being correct.
| Item | Required Setting | Notes |
|---|---|---|
| CPU | ET200SP S7-1500 (e.g., 6ES7510-1DJ02-0AB0, 6ES7512-1DK02-0AB0) | Firmware V2.5 or later recommended for the Modbus_PN_CPU library V3.x |
| CM PtP module | 6ES7137-6AA00-0BA0 (RS-232/422/485) or 6ES7137-6BD00-0BA0 (RS-485 only) | Plugged into an ET200SP BaseUnit type A0 or A1 |
| BaseUnit | Open-style (no AUX terminals) for RS-485; BU type depends on grounding concept | See ET200SP system manual, section "BaseUnits for serial interface" |
| TIA Portal library | MODBUS_PN_CPU V3.1 or later (part of TIA Portal V16+) | Contains FB 1078 / FB 1080 / FB 1081 |
| Bus termination | 120 Ω at each bus end, switchable on CM PtP DIP | Enable only at the two physical ends of the RS-485 segment |
| Shielding | Shield grounded at one end only; DRAIN wire to PE bar | Avoid ground loops on multi-node segments |
The CM PtP module's hardware identifier (HID) — referred to in TIA Portal as the Port or Hardware Identifier of the module — must be passed correctly to Modbus_Comm_Load on input PORT. Typical HID values for ET200SP systems are in the range of 100–1023 depending on the slot index. The example field experience below uses HID 263 for a CM PtP inserted in slot 3 of an ET200SP station, which is a legitimate value for a 1510SP / 1512SP station when the slot numbering uses the default configuration.
Register Addressing: Modbus Convention vs S7 Data Block Offsets
The most common source of confusion when an external master (or an external slave device's documentation) requests a Modbus register address is the offset translation between the Modbus 5-digit register number and the byte offset inside the S7 data block referenced by the Modbus block.
The Modbus specification defines four address spaces, and the leading digit of the 5-digit address selects which space is being referenced. Function code pairs govern each space:
| Modbus Address Range | Space | Function Codes | S7-1500 Data Type | DB Offset Rule |
|---|---|---|---|---|
| 00001 – 09999 | Coils (boolean outputs) | 01, 05, 15 | Bit array / BOOL | Bit n of byte floor((n-1)/8) |
| 10001 – 19999 | Discrete inputs | 02 | Bit array / BOOL | Bit n of byte floor((n-1)/8) |
| 30001 – 39999 | Input registers (read-only words) | 04 | WORD / INT / REAL | Word at byte offset 2·(n-30001) |
| 40001 – 49999 | Holding registers (read/write words) | 03, 06, 16 | WORD / INT / REAL | Word at byte offset 2·(n-40001) |
Concretely, the answer to the source's first question is yes: the holding register 40001 maps to the data word at byte offset 0 of the Modbus DB — i.e. DBW0 — and the register 40002 maps to DBW2. The full linear formula is:
DBW_offset = 2 × (Modbus_register − 40001)
Equivalently: byte offset = 2 × (register − base). For input registers, replace the base with 30001. Discrete inputs and coils are bit-based and use:
DBB_offset = floor((Modbus_bit − 10001) / 8) // for 1xxxx
DBX_bit = (Modbus_bit − 10001) MOD 8
The Modbus DB used as the data backing store must be created with non-optimized access in TIA Portal. Optimized (symbolic-only) DBs do not expose the fixed byte offsets the Modbus blocks need for the DATA_ADDR / DATA_PTR parameters.
DATA_ADDR in the Modbus_Master/Slave block. Always verify the convention of the third-party device by reading a single known value at register 40001 first.Block Architecture: Where Each Block Is Called
Three blocks form a Modbus RTU point-to-point link. Each is called from a specific OB and never from any other OB.
| Block | Called From | Trigger Condition | Inputs Required |
|---|---|---|---|
| Modbus_Comm_Load | OB 100 (warm restart) or first scan of OB 1 with a rising-edge enable | Once per session; do not call in a fast cyclic OB | REQ, PORT, BAUD, PARITY, FLOW_CTRL, RESP_TO, MODE (RTU) |
| Modbus_Slave | OB 1 (cyclic main) | Every cycle when the CPU is the slave | MB_ADDR, MODE (0 = RTU), DATA_ADDR, DATA_LEN, DATA_PTR |
| Modbus_Master | OB 1 (cyclic main) or OB 35 (timed interrupt) for deterministic polling | Once per transaction triggered by REQ | REQ, MB_ADDR, MODE, DATA_ADDR, DATA_LEN, DATA_PTR, WRITE_READ |
The answer to the second question in the source is therefore: only one of Modbus_Master or Modbus_Slave is called, never both. The two blocks are mutually exclusive on a single CM PtP port. If the external device is the master, the S7-1500 calls only Modbus_Slave. If the S7-1500 must poll an external device, it calls only Modbus_Master plus the initial Modbus_Comm_Load.
Slave Configuration: External Master Reads the S7-1500
When the third-party SCADA is the master and reads analog values from the ET200SP, the program structure is:
// OB 100 - warm restart, runs once
IF "First_Scan" THEN
"Modbus_Comm_Load_DB"(REQ := TRUE,
PORT := 263,
BAUD := 9600,
PARITY := 0, // 0 = even, 1 = odd, 2 = none
FLOW_CTRL := 0, // 0 = no flow control
RESP_TO := 1000, // ms
MODE := 0); // 0 = RTU
END_IF;
// OB 1 - cyclic
"Modbus_Slave_DB"(MB_ADDR := 1, // slave number 1..247
MODE := 0, // RTU
DATA_ADDR := 0, // pointer to MB_DB starts at offset 0
DATA_LEN := 100, // number of holding-register WORDS exposed
DATA_PTR := "MB_DB");
The MB_DB must be a non-optimized DB containing at least 200 bytes (100 words). Holding register 40001 maps to MB_DB.DBW0, 40002 to MB_DB.DBW2, and so on. The external master reads with function code 03 and registers 40001..40100 to obtain the full block.
Master Configuration: S7-1500 Writes to an External Slave
When the third-party device is the slave and the S7-1500 is the polling master, the program structure is:
// OB 100 - one-shot
IF "First_Scan" THEN
"Modbus_Comm_Load_DB"(REQ := TRUE,
PORT := 263,
BAUD := 9600,
PARITY := 0,
FLOW_CTRL := 0,
RESP_TO := 1000,
MODE := 0);
END_IF;
// OB 1 - cyclic, one transaction per call
"Modbus_Master_DB"(REQ := "Mbus_Trigger",
MB_ADDR := 1,
MODE := 0,
DATA_ADDR := 40001,
DATA_LEN := 1,
DATA_PTR := "MB_DB",
WRITE_READ := 0); // 0 = read, 1 = write
For deterministic behaviour at 100 ms the Modbus_Master call is best placed in OB 35 (cyclic interrupt) with a 100 ms period. The master will not initiate a second transaction while Modbus_Master.DONE or Modbus_Master.ERROR is TRUE from a previous call. Driving REQ from a 100 ms clock pulse gated by the inverse of DONE OR ERROR produces reliable, single-shot transactions.
Field-Proven Workaround: Single-Word Cyclic Sweep
When the master is the S7-1500 and must write several consecutive words to a slave that is sensitive to multi-register write timing, a deterministic single-word sweep eliminates the problem. This is the technique the source author used successfully:
- Create a non-optimized
Sweep_DBwith a structure of{ index : INT; payload : ARRAY[0..49] OF WORD }. - On every 200 ms OB 35 tick, increment
Sweep_DB.indexmodulo 50. - Copy the current
Sweep_DB.payload[index]to the head ofMB_DBat byte offset 0. - Trigger
Modbus_MasterwithDATA_ADDR = 40001,DATA_LEN = 1. - Reset the trigger once
DONEorERRORis set.
Total update period for 50 words is 10 s, which is acceptable for non-critical analog mirroring. For sub-second update rates, group the writes into 8-word FC16 frames and increase OB 35 to 50 ms; the multi-word write problem reported in the source is generally a slave-device limitation, not a Modbus protocol issue.
Error Code Reference: 16#81E2 and 16#81E7
Both error codes are returned in Modbus_Master.STATUS (or Modbus_Slave.STATUS) and indicate failures of the Modbus transaction at the protocol level. They are not PLC error codes — the CPU does not stop — but they do mean that the current REQ was not completed.
| STATUS (hex) | Meaning | Typical Root Cause | Corrective Action |
|---|---|---|---|
| 16#81E2 | Negative acknowledgement: slave rejected the function code | Slave device does not support the requested FC (e.g., trying FC16 on a device that only supports FC06); or the Modbus address is outside the slave's range | Reduce DATA_LEN to 1 and try FC03/FC06; verify the slave documentation supports the requested function code; verify the slave's declared register range covers DATA_ADDR |
| 16#81E7 | Illegal data address | The Modbus address referenced in DATA_ADDR does not exist in the slave; or the address is in the wrong space (4xxxx vs 3xxxx vs 1xxxx) | Cross-check the slave's Modbus map; ensure the address is in the holding-register (4xxxx) range when using FC03/06/16, or input-register (3xxxx) range when using FC04 |
Both codes typically appear at the start of communication and may be transient on some slave devices during the first transaction after link establishment. If they appear once and then disappear on subsequent transactions, they are usually caused by the slave's UART not yet being ready when the first poll arrives; the recommended mitigation is to ignore ERROR for the first three transactions, or to add a 500 ms post-MB_Comm_Load delay using a TON timer before triggering the first Modbus_Master call.
The FB 613 Peripheral Access Error
When the CPU enters STOP and the diagnostic buffer shows:
"Error in read access to the periphery (address I 0) in FB 613"
the root cause is almost always a misconfiguration of the hardware identifier passed to Modbus_Comm_Load or the slot assignment of the CM PtP module. FB 613 is the lower-level system FB that the Modbus library blocks use to read the CM PtP module's hardware configuration; when PORT is set to 0 or to a value that does not correspond to a real CM PtP slot, FB 613 attempts to read the I/O image at address I 0.0 of a non-existent peripheral and triggers an OB 121 peripheral-access fault, which in turn puts the CPU in STOP.
The corrective steps are:
- Open the device configuration of the ET200SP station in TIA Portal.
- Click the CM PtP module and note the value in the Properties → System constants → Hardware Identifier field. Typical values: 100, 101, 102 ... or higher depending on slot count. The example in the source used 263, which is a valid value for a slot 3 module on a fully loaded ET200SP station.
- Confirm that the same value is wired to
Modbus_Comm_Load.PORT, that the constantPORT_Constantused in any user code is also 263, and that the slot of the physical module matches the slot shown in the device view (a swapped module in a different slot will also cause this fault). - Recompile and download. The diagnostic-buffer entry will clear after the next STOP-to-RUN transition.
Modbus_Comm_Load alone is also non-fatal because it does not attempt to read I/O; the fault is raised only by Modbus_Master / Modbus_Slave during the per-cycle read of the port status. Always evaluate Modbus_Comm_Load.ERROR and Modbus_Comm_Load.STATUS on the first scan — if the load fails, do not call the master or slave blocks until the load succeeds.Diagnostic: SaveStatus Library Interpretation
For deeper diagnosis, Siemens publishes a sample library called SaveStatus on the Siemens Industry Online Support portal. The library contains a function block that copies the 4-byte STATUS and STATUS_2 outputs of the Modbus blocks into a 10-DWord array for trend recording and HMI display. The mapping inside the 10-DWord array is:
| Array Index | Source | Description |
|---|---|---|
| 0 | Modbus_Master.ERROR | BOOL rolled into DWord — TRUE on any error |
| 1 | Modbus_Master.STATUS (word 0) | Low word of the 4-byte status |
| 2 | Modbus_Master.STATUS (word 1) | High word of the 4-byte status |
| 3 | Modbus_Master.STATUS_2 | Extension for additional diagnostics on firmware V2.9+ |
| 4 | Modbus_Master.DONE | BOOL rolled into DWord — TRUE on successful completion |
| 5 | Modbus_Master.BUSY | BOOL rolled into DWord — TRUE while a transaction is in progress |
| 6..9 | User-defined extension area | Spare DWords; the sample library leaves them as zero |
The 4-byte STATUS field is decoded as follows: the low word is the same value as in older single-word returns (e.g., 16#81E2). The high word indicates the call-stack location of the failure (0 = Modbus_Comm_Load, 1 = Modbus_Master / Slave, 2 = CM PtP firmware, 3 = driver). For example, STATUS = 16#000181E2 means: low word 16#81E2, raised in the Modbus_Master / Slave block (high word = 1).
Cable, Wiring, and Port Identifier Issues
Approximately 30% of all Modbus RTU commissioning problems on ET200SP are physical-layer issues. The most frequent mistakes are:
| Symptom | Likely Cause | Resolution |
|---|---|---|
| STATUS = 16#8180 / 16#8181 with no reply | TX / RX swap on RS-485 2-wire (D+ ↔ D−) or TX / RX swap on RS-232 (TD ↔ RD) | Swap the data pair. On the ET200SP CM PtP, the screw terminals are clearly labeled: TD-A / TD-B for transmit pair; RD-A / RD-B for receive pair. On 2-wire RS-485, jumper TD-A to RD-A and TD-B to RD-B at the module terminals; only one pair exists on the bus |
| STATUS = 16#81E7 on first poll, OK thereafter | Slave UART not ready at first poll, or the "slave enable" output is not asserted when the master polls | Add 500 ms post-MB_Comm_Load delay; poll once with FC02 (read input status) as a warm-up |
| STATUS = 16#81E2 only for FC16 multi-write | Slave does not support FC16; some low-end SCADA/HMI slaves only support FC06 single-word writes | Fall back to FC06 single-word writes; perform the single-word sweep described earlier |
| CPU STOP with FB 613 fault | PORT constant is 0 or otherwise invalid | Recheck the hardware identifier of the CM PtP in the device view; update the constant in the global constants table |
| Intermittent 16#81E2 with shielded cable | Ground loop on long cable run, GND not bonded at one end only | Bond shield at one end only; ensure DRAIN wire to PE bar at the head-end only; verify CM PtP "DCM" DIP switch is set to "isolated" if the device is fully floating |
| All registers return 0xFF, 0xFE, 0xFF... | RS-485 termination missing at one or both ends | Enable the 120 Ω termination DIP on the CM PtP and at the physical end-of-line slave |
Verification and Commissioning Checklist
Run the following checks in order before declaring the link operational:
-
Hardware identifier check. Verify the
Modbus_Comm_Load.PORTconstant matches the value in TIA Portal's device view, and that the CM PtP's slot is populated in the physical rack. - Parameter consistency check. Confirm BAUD, PARITY, DATA_BITS, STOP_BITS and RESP_TO match between the CPU and the external device to the bit.
- Loopback test. With the bus physically disconnected, connect a small terminal program (e.g., any Modbus master simulator) to the CM PtP and read holding register 40001 from MB_DB with DATA_LEN = 1. The result must match the value placed in MB_DB.DBW0.
-
Modbus_Comm_Load status. After the first scan,
Modbus_Comm_Load.DONEmust be TRUE andModbus_Comm_Load.ERRORmust be FALSE. If ERROR is TRUE, decodeSTATUSagainst the Modbus_Comm_Load error table before calling the master / slave block. - First-transaction check. Force a known value into MB_DB.DBW0 and poll register 40001 from the external master. The polled value must match.
- Full register sweep. Step DATA_LEN through 1, 2, 5, 10, 50, 100 to find the slave's maximum supported multi-register read length.
- Long-run stability check. Run the master for at least 30 minutes and log SaveStatus array index 1 (STATUS) to confirm no transient 16#81E2 / 16#81E7 values are still present.
Troubleshooting Matrix
| Observed Symptom | First Check | Second Check | Third Check |
|---|---|---|---|
| CPU STOP, FB 613 in buffer | PORT constant validity | CM PtP slot match | OB 121 programming error OB presence |
| STATUS 16#81E2 | Slave FC support | Slave register range | Single-word vs multi-word test |
| STATUS 16#81E7 | Address space (3xxxx vs 4xxxx) | Offset 1-based vs 0-based | Slave register range upper limit |
| STATUS 16#81E0 / 16#81E1 | Electrical / physical layer | Baud rate match | Cable swap TX/RX |
| STATUS 16#7000 forever | REQ never pulses | OB 35 not running | Modbus_Comm_Load not done |
| Intermittent dropouts | Termination resistors | Shield bonding | RESP_TO too short |
Standards and Reference Material
For arbitration between two masters and for the electrical layer the following are the controlling documents; the implementation in the CM PtP module conforms to them.
- Modbus Application Protocol V1.1b3 — register model and function codes
- Modbus over Serial Line V1.02 — RTU framing, baud, parity, inter-character timing
- Siemens CM PtP manual (109769500) — wiring, RS-485 termination DIPs
- MODBUS_PN_CPU library documentation (109751302) — block interface and error codes
Does Modbus holding register 40001 correspond to DBW0 of the Modbus data block?
Yes. Holding register N maps to the word at byte offset 2·(N−40001) in the Modbus DB; therefore 40001 = DBW0, 40002 = DBW2, 40100 = DBW198, and so on. The DB must be non-optimized access in TIA Portal so that the byte offsets are visible to the Modbus block.
Should both Modbus_Master and Modbus_Slave be called when the S7-1500 talks to a Modbus RTU device?
No. Modbus_Master and Modbus_Slave are mutually exclusive on a single CM PtP port. Call only the block that matches the role of the S7-1500 in the link: Modbus_Slave when an external device is the master reading the PLC, Modbus_Master when the PLC polls an external slave. In both cases Modbus_Comm_Load must be called once on the first scan to parameterize the port.
What does the diagnostic buffer entry "Error in read access to the periphery (address I 0) in FB 613" mean?
FB 613 is the lower-level system FB the Modbus library uses to access the CM PtP module. The fault indicates that the hardware identifier passed to Modbus_Comm_Load.PORT is 0 or does not correspond to a real CM PtP slot, so the read of the port status failed. Correct the PORT constant to the value shown in the device view of TIA Portal and reload the project; the fault will clear on the next RUN transition.
What do error codes 16#81E2 and 16#81E7 indicate, and how are they resolved?
16#81E2 is a negative acknowledgement from the slave — the slave does not support the requested function code or the address is outside its declared range. 16#81E7 is an illegal data address — the Modbus address does not exist in the slave. Resolution is to verify the slave's Modbus map against the configured DATA_ADDR and DATA_LEN, switch from FC16 to FC06 if the slave does not support multi-word writes, and confirm the address space is 4xxxx (holding) for FC03/06/16 or 3xxxx (input) for FC04.
Why is the SaveStatus library's array 10 DWords long when the Modbus STATUS is only 4 bytes?
The SaveStatus sample library allocates 10 DWords to provide space for both STATUS and STATUS_2 (the latter was added in library V3.x for firmware V2.9+), plus boolean flags DONE, BUSY, ERROR rolled into DWords, and four spare DWords for user-defined extension. Indices 0 through 5 carry the live status of the Modbus block; indices 6 through 9 are user-reserved and are zero unless the integrator populates them.