Resolving S7-1500 Modbus RTU Single-Bit Write Errors on CM 1541-1
Engineers integrating a Siemens S7-1500 CPU (S7-1511, S7-1513, S7-1515, S7-1516, S7-1518) with a third-party Modbus RTU slave through a CM 1541-1 or CP 1541-1 module frequently hit a stubborn fault: single-bit coil writes fail, multi-bit writes work, and word-level reads/writes are stable. The fault traces to a Modbus FC05 implementation gap in the slave. This reference documents the exact cause, the diagnostic procedure to confirm it, and the configuration change that resolves it without swapping hardware or firmware on the PLC.
1. Problem Statement
Configuration: TIA Portal V14 SP1 (also applies to V15, V15.1, V16, V17, V18, V19, V20), S7-1500 family CPU, CM 1541-1 (RS485/422, 6GK7541-1AB00-0AA0) or CP 1541-1 (RS485/422, 6GK7541-1AX00-0XE0), Modbus_Master instruction from the standard MODBUS (RTU) library.
Observed behavior on the master:
- Read Holding Registers (MODE=5) — OK
- Write Single Register (MODE=6, LEN=1) — OK
- Write Multiple Registers (MODE=7, LEN=1..123) — OK
- Read Coils (MODE=0, LEN=1..2000) — OK
- Write Single Coil (MODE=1, LEN=1) — ERROR on slave addresses 1..9999
- Write Single Coil (MODE=1, LEN=2) — OK on most slave firmware revisions (non-standard behavior, not guaranteed)
- Write Multiple Coils (MODE=2, LEN=1..1968) — OK
The Modbus_Master instruction raises ERROR=TRUE with a STATUS code that pins the failure to the slave. The most common STATUS seen on the S7-1500 is 0x8180 (slave returned exception 01, ILLEGAL FUNCTION), followed by 0x8380 (exception 03, ILLEGAL DATA VALUE) on slaves that silently parse the FC05 PDU and reject it downstream.
2. Affected Hardware and Firmware
| Component | Order number | Firmware | Notes |
|---|---|---|---|
| CM 1541-1 (RS485/422) | 6GK7541-1AB00-0AA0 | ≥ V1.0 | Discontinued, replaced by CP 1541-1 |
| CP 1541-1 (RS485/422) | 6GK7541-1AX00-0XE0 | ≥ V1.0, full MODE 0..14 from V2.0 | Current product |
| CP 1542-1 (RS232) | 6GK7542-1AX00-0XE0 | ≥ V1.0 | RS-232 only, no bus termination |
| S7-1500 CPU | 6ES751x-xxx..-AB0 | ≥ V1.8 for full instruction set | All S7-1500 / ET 200MP CPUs |
| TIA Portal | — | V14 SP1 .. V20 | Modbus (RTU) library ships with all versions |
Confirm the installed module firmware with the online diagnostics in TIA Portal (online → accessible nodes → module → diagnostics → module information). For the CP 1541-1, the firmware can be updated using the Siemens support tool. Refer to the module's product page and the TIA Portal Help entry "Modbus (RTU) (S7-1200, S7-1500)" for the firmware dependency of the diagnostic instructions.
3. Technical Background: Modbus Function Codes for Coil Writes
The Modbus protocol defines two separate function codes for writing coils. They are not interchangeable on the slave side; each has its own PDU encoding and parser:
| Property | FC05 — Write Single Coil | FC15 — Write Multiple Coils |
|---|---|---|
| PDU request size | 4 bytes (fixed) | 5 + N bytes (variable, N = byte count of bit-packed data) |
| Coils written per request | Exactly 1 | 1..1968 |
| Value encoding | 0xFF00 = ON, 0x0000 = OFF | 1 bit per coil, packed LSB-first into bytes |
| Response echo | Echo of the request PDU | Coil address + quantity, no data echo |
| Slaves that implement it | Subset (often buggy) | Virtually all |
Wire-level RTU frames for the two function codes look like this (slave address 0x01, coil address 0x000A = 10):
FC05 write of one coil at address 10, value = ON
[01] [05] [00] [0A] [FF] [00] [CRC_LO] [CRC_HI] (8 bytes total)
FC15 write of one coil at address 10, value = ON
[01] [0F] [00] [0A] [00] [01] [01] [01] [CRC_LO] [CRC_HI] (10 bytes total)
Both frames achieve the same end state: a single coil flips at address 10. The FC15 frame adds two bytes (quantity + byte count) plus one byte of bit-packed data, but it is functionally equivalent for a single bit. The inter-frame silent interval of 3.5 character times (t3.5) is the same.
4. Siemens Modbus_Master MODE Mapping
The Modbus_Master FB from the MODBUS (RTU) library in TIA Portal accepts a MODE input that selects the underlying Modbus function code. The mapping is fixed in firmware and cannot be modified by the user:
| MODE | Modbus FC | Function | DATA_LEN range | DATA_PTR type |
|---|---|---|---|---|
| 0 | 01 | Read Coils | 1..2000 | BOOL array / DBX |
| 1 | 05 | Write Single Coil | 1 | BOOL |
| 2 | 15 (0x0F) | Write Multiple Coils | 1..1968 | BOOL array / DBX |
| 3 | 02 | Read Discrete Inputs | 1..2000 | BOOL array / DBX |
| 4 | 04 | Read Input Registers | 1..125 | WORD / INT array |
| 5 | 03 | Read Holding Registers | 1..125 | WORD / INT array |
| 6 | 06 | Write Single Register | 1 | WORD / INT |
| 7 | 16 (0x10) | Write Multiple Registers | 1..123 | WORD / INT array |
| 8 | 23 (0x17) | Read/Write Multiple Registers | R 1..125, W 1..121 | WORD / INT array |
| 9..14 | Various | Diagnostic / vendor-specific | FW-dependent | FW-dependent |
Refer to the TIA Portal Help topic "Modbus_Master / Modbus_Comm_Load" and the Communicate as Modbus master (S7-1200, S7-1500) manual for the exact FW dependency of MODE 8 and beyond. The CP 1541-1 product page on the Siemens support portal (search order number 6GK7541-1AX00-0XE0) lists the current firmware release and the supported function code set.
5. Root Cause Analysis
The S7-1500 master transmits the request and waits for a response. With MODE=1 and DATA_LEN=1, the master correctly issues an FC05 request. The slave's response falls into one of three categories:
-
Exception 01 (ILLEGAL FUNCTION, 0x81): Slave does not implement FC05 at all. This is the most common cause in the field. The S7 master translates this into STATUS
0x8180. -
Exception 02 (ILLEGAL DATA ADDRESS, 0x82): Slave has a separate handler for FC05 that performs an address-range check; the address is outside the slave's coil map for FC05 but inside it for FC15. STATUS
0x8280. -
Exception 03 (ILLEGAL DATA VALUE, 0x83): Slave receives the FC05 PDU and tries to parse the value field but fails (often because the engineer hard-coded the parser to expect 0xFF00 in big-endian and the slave is little-endian, or the parser mis-handles the response echo). STATUS
0x8380.
All three causes point to the same conclusion: the slave's FC05 path is broken or absent. Switching the master to FC15 (MODE=2) routes the request through the slave's FC15 handler, which is almost always present and well-tested.
6. Wire-level Sequence Diagram
7. Diagnostic Procedure
- Verify the physical layer. Confirm RS-485 2-wire (half-duplex) vs 4-wire (full-duplex) vs RS-232. The CP 1541-1 supports both 2-wire and 4-wire via the on-board DIP switch; the CP 1542-1 is RS-232 only. Confirm 120 Ω termination at both ends of an RS-485 trunk. Confirm bias resistors are enabled on at most one device (the CP 1541-1 has a DIP switch for this).
-
Match baud, parity, and framing. The CP 1541-1 supports 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200 baud with 7E1, 8E1, 8N1, 8N2. The slave's DIP switches or configuration software must match exactly. A parity mismatch produces STATUS
0xC091on the master. -
Capture STATUS on the failing job. Add a WORD tag in a non-optimized DB to receive
Modbus_Master.STATUS. On a rising edge ofERROR, copy STATUS to a buffer for trend analysis. The reference for STATUS values is the MODBUS (RTU) (S7-1200, S7-1500) error messages help topic. -
Reproduce on a PC-based Modbus tool. Disconnect the S7-1500 from the bus (or pause its Modbus_Master cycle), connect a USB-to-RS485 converter to a laptop, and run a Modbus RTU master utility (Modbus Poll, QModMaster, or a
libmodbus-based script). Issue an FC05 write to the same coil address with quantity=1.- If the utility also reports exception 01, the slave does not support FC05. Continue to step 5.
- If the utility reports exception 02 or 03, the slave implements FC05 but rejects this specific request; verify the coil address range in the slave documentation.
- If the utility reports success, the S7 master has a separate problem (cabling, timing, address translation). Continue to step 6.
- Test FC15 on the same utility. With the S7-1500 still disconnected, issue an FC15 write to the same coil with quantity=1. If this returns success, the slave's FC15 handler is the only working code path. Reconfigure the S7 master to MODE=2 with DATA_LEN=1.
- If the utility reports success for FC05 but the S7 master still fails, check the t3.5 inter-frame gap. Some slaves tolerate the master's gap; others require a longer or shorter gap. Adjust the port's inter-frame delay in the CM/CP 1541-1 properties. Also verify that the slave ID in MB_ADDR matches the slave's address (1..247), that the offset is 0-based, and that the DB used for DATA_PTR is non-optimized.
8. Solution A — Use MODE=2 (FC15) for Single-Bit Writes
Reconfigure the failing Modbus_Master call as follows:
-
MB_ADDR= slave station address (1..247) -
MODE= 2 (FC15, Write Multiple Coils) -
DATA_ADDR= target coil address. Siemens uses 0-based addressing for coil offsets 0..9998. If the slave vendor documents 1-based addresses, add 1 to convert. For example, vendor coil "10" → S7 offset 9 (or 10 if the slave is also 0-based; check the slave's map). -
DATA_LEN= 1 -
DATA_PTR= address of a BOOL tag or a DBX bit that holds the desired state (TRUE = ON, FALSE = OFF). The data block must be non-optimized.
Functionally, the wire-level request is a single-bit write. The slave writes the bit, returns a normal response, and the S7 master raises DONE for one scan. STATUS remains 0x0000 on success.
DATA_PTR for MODE=2 must point to a non-optimized data block or a bit in a standard memory area (M, Q, I). Optimized access DBs are not permitted and produce STATUS 0x0003. See the MODBUS (RTU) error reference.9. Solution B — Legacy LEN=2 Workaround (Not Recommended)
If the slave rejects FC05 with quantity=1 but accepts FC05 with quantity=2, you can keep MODE=1 and set DATA_LEN=2. Bit 0 is the real coil, bit 1 is a "don't care" coil that flips with every write. This is brittle:
- It only works on slaves with a non-conformant FC05 parser that actually treats LEN=2 as a multi-coil request.
- It mutates an adjacent coil on every write, which can corrupt the slave's state if that coil controls a real output.
- It is not portable across slave firmware revisions.
Use this only as a temporary bridge while the slave vendor patches the FC05 handler. Permanent fix is Solution A.
10. Solution C — Compatibility Mode (Not a Fix for FC05 Issues)
The Compatibility mode checkbox in the CM 1541-1 / CP 1541-1 port properties changes the inter-frame response timeout and the silent interval behavior. It does not change the function code selected by the MODE parameter. A slave that does not implement FC05 will still reject the request when Compatibility mode is on. Enable it only when the slave documentation explicitly requires it, or when integrating with very old equipment (pre-2000) that uses a non-standard gap.
11. Configuration Procedure in TIA Portal
- Insert the module. Open the S7-1500 device configuration, drag the CP 1541-1 (or CM 1541-1) from the hardware catalog under "Communications modules" → "Modbus" into a free slot. Confirm the firmware version in the catalog matches the module's installed firmware.
-
Configure the port. Open the module's properties, select "Port configuration", and set:
- Operating mode: Modbus master (RTU)
- Baud rate, parity, stop bits to match the slave
- Inter-frame delay: 3.5 character times (default) or 50 ms for very old slaves
- Response timeout: 1000 ms (adjust for slow slaves)
- Compatibility mode: as required by slave
- Set the DIP switches on the physical module. The CP 1541-1 has a 4-position DIP switch: termination (on/off), bias (on/off), 2-wire/4-wire, and a reserved position. The DIP switch must agree with the software port configuration.
-
Add the Modbus_Comm_Load instance. From the program blocks, drop
Modbus_Comm_Loadfrom "Communication" → "Modbus RTU". Configure it with the module's hardware identifier (from the system constants) and assign an instance DB (e.g.,iDB_Modbus_Comm_Load). Call this FB once at startup; the DONE output enables the Modbus_Master jobs. -
Add the Modbus_Master instance. Drop
Modbus_Masterfrom the same palette. Assign a second instance DB (e.g.,iDB_Modbus_Master_Coils). Configure MODE, DATA_ADDR, DATA_LEN, and DATA_PTR per Solution A above. The DATA_PTR must reference a BOOL in a non-optimized DB (e.g.,"DB_Coils".Bit10). - Build, download, and go online. Compile the project, download to the CPU, and go online. Open the instance DBs in the watch table and confirm DONE pulses TRUE on each request, ERROR remains FALSE, and STATUS = 0x0000.
12. SCL Code Example — Single-Bit Write Using FC15
// One-shot trigger for a single-bit write to a Modbus RTU slave.
// Pre-conditions: Modbus_Comm_Load has been called and DONE is TRUE.
// The instance DB "iDB_Modbus_Master_Coils" is the Modbus_Master IDB.
// "DB_Coils" is a non-optimized data block with a BOOL tag "Bit10".
IF "Start_Single_Write" THEN
"iDB_Modbus_Master_Coils".REQ := TRUE;
"iDB_Modbus_Master_Coils".MB_ADDR := 1; // Slave ID 1
"iDB_Modbus_Master_Coils".MODE := 2; // FC15 — Write Multiple Coils
"iDB_Modbus_Master_Coils".DATA_ADDR := 10; // Coil offset 10 (0-based)
"iDB_Modbus_Master_Coils".DATA_LEN := 1; // Single bit
"iDB_Modbus_Master_Coils".DATA_PTR := "DB_Coils".Bit10; // BOOL, non-optimized DB
"Start_Single_Write" := FALSE;
END_IF;
// Reset REQ on completion; capture STATUS for diagnosis on error.
IF "iDB_Modbus_Master_Coils".DONE OR "iDB_Modbus_Master_Coils".ERROR THEN
"iDB_Modbus_Master_Coils".REQ := FALSE;
IF "iDB_Modbus_Master_Coils".ERROR THEN
"Last_STATUS" := "iDB_Modbus_Master_Coils".STATUS;
"Last_Error_Time" := SYSTEM_TIMESTAMP();
END_IF;
END_IF;
13. STATUS Code Reference
| STATUS (hex) | Cause | Recommended action |
|---|---|---|
| 0x0000 | OK | — |
| 0x0001 | MB_ADDR invalid (0 or > 247) | Verify slave ID 1..247 |
| 0x0002 | MODE invalid for the loaded port configuration or FW | Re-check MODE against the table; update module FW |
| 0x0003 | DATA_PTR / DATA_LEN out of range, or DB is optimized | Use non-optimized DB; verify DB number exists |
| 0x0004 | DATA_LEN invalid for the selected MODE | Match LEN to MODE table (e.g., MODE=1 requires LEN=1) |
| 0x0007 | Data area overlaps another active use | Use distinct DBs per concurrent job; serialize requests |
| 0x8180 | Slave exception 01 — ILLEGAL FUNCTION | Slave does not implement FC05; switch to MODE=2 |
| 0x8280 | Slave exception 02 — ILLEGAL DATA ADDRESS | Coil address outside slave's map; check slave docs |
| 0x8380 | Slave exception 03 — ILLEGAL DATA VALUE | Check CRC, baud, parity, termination |
| 0xC091 | Port configuration error | Re-run Modbus_Comm_Load; check module FW |
| 0xC092 | Response timeout | Increase response timeout; check slave power |
| 0xC093 | CRC error on the response | Check wiring, termination, EMI, baud rate |
For the full list refer to the MODBUS (RTU) (S7-1200, S7-1500) error messages help topic and the CP 1541-1 product documentation. The error reference covers the local master-side errors (0x0001..0x0007, 0xC0xx) and the Modbus exception codes returned by the slave (0x80 + exception code).
14. Verification Procedure
- With MODE=2 and DATA_LEN=1, trigger the job. DONE pulses TRUE for one scan; STATUS = 0x0000; ERROR remains FALSE.
- Confirm the coil on the slave changed state using the slave's HMI, web interface, or by reading the same coil back with a separate Modbus_Master call (MODE=0, LEN=1).
- Run a 24-hour stress test that toggles the coil at 100 ms intervals. ERROR must remain FALSE, STATUS must remain 0x0000, and the round-trip time (REQ rising edge to DONE rising edge) must remain stable within ±10%.
- Reconnect the laptop with the Modbus RTU master utility and verify the same coil is being polled by an independent tool. This rules out confusion about which slave is responding on a multi-drop RS-485 bus.
- Trend STATUS and round-trip time in WinCC Unified or a TIA Portal HMI to detect intermittent issues that the online watch table misses.
15. Multi-Slave and Multi-Job Considerations
On an RS-485 trunk with multiple slaves, each slave must have a unique MB_ADDR in the 1..247 range. A single CM/CP 1541-1 port supports multiple Modbus_Master jobs as long as each job has its own instance DB and the jobs are serialized (the instruction is non-reentrant). A typical pattern is to use a state machine in the OB1 cycle to dispatch one job per PLC scan, or to use a 100 ms cyclic OB for periodic polling.
If a downstream slave accepts FC05 and the upstream slave does not, implement two parallel Modbus_Master jobs with different MB_ADDR and DATA_PTRs, each configured with the correct MODE. The dispatcher selects the right job at runtime. This pattern is common on mixed-vendor Modbus installations where one controller is a legacy PAC and another is a modern sensor.
16. Related Topics
The same conceptual problem — single-bit write fails, multi-bit write succeeds — appears on the Modbus TCP side. When a Modbus TCP server is implemented by a Siemens S7-1500 CPU (acting as a Modbus TCP server on its PROFINET interface), some SCADA clients try to write a single bit to a holding-register address using FC05. The server rejects the request because the address is a register, not a coil. The workaround in the SCADA client is to construct a 16-bit mask and use FC16 to write the full register with the target bit set, leaving the other 15 bits unchanged. The lesson is the same: a server that does not support FC05 on its coil map will not support FC05 on its holding-register map either, and FC16 (or FC15 for coils) is the universal fallback.
For S7-1200 systems using the CM 1241 (RS485/422, 6ES7241-1CH32-0XB0) or CM 1241 (RS232, 6ES7241-1AH32-0XB0), the same MODE mapping applies and the same solution (MODE=2 for single-bit writes) resolves the issue. The TIA Portal Help topic "Modbus_Master / Modbus_Comm_Load" covers both CPU families.
17. Best Practices Summary
- Always prefer FC15 (MODE=2) for single-bit writes when the slave's FC05 implementation is suspect. FC15 is functionally equivalent for a single bit and is supported by virtually all modern Modbus RTU slaves.
- Use a non-optimized data block for the data pointer. The Modbus instructions reject optimized blocks with STATUS 0x0003 on S7-1500.
- Call
Modbus_Comm_Loadonly once at startup, with DONE feeding the enable logic of theModbus_Masterjobs. Do not callModbus_Comm_Loadcyclically — it re-binds the port and disrupts active jobs. - Use a single instance DB per concurrent
Modbus_Masterjob. The instruction is non-reentrant; concurrent calls to the same instance DB produce undefined behavior. - Add 120 Ω termination at each end of the RS-485 trunk. Enable bias resistors on at most one device (the CP 1541-1 has a DIP switch for this).
- Capture STATUS into a non-optimized DB on every rising edge of ERROR. Trend the values in WinCC Unified or a TIA Portal HMI to detect intermittent issues.
- Keep the inter-frame gap at the default 3.5 character times. Increase to 50 ms only for slaves that explicitly require it.
- When integrating with a new slave vendor, perform the FC05/FC15 test on a PC-based Modbus utility first. If FC05 fails, document it and standardize on MODE=2 for the project.
FAQ
Why does my S7-1500 master fail with STATUS 0x8180 when writing a single coil with MODE=1?
STATUS 0x8180 means the slave returned Modbus exception 01 (Illegal Function) for the FC05 Write Single Coil request. The slave firmware does not implement FC05. Switch the MODE parameter to 2 so the master uses FC15 (Write Multiple Coils) with DATA_LEN=1. The wire-level encoding is functionally equivalent for a single bit and is supported by virtually all modern Modbus RTU slaves.
Is there a Compatibility Mode that fixes single-bit write errors on CM 1541-1?
No. The Compatibility Mode checkbox in the CM 1541-1 / CP 1541-1 port properties changes the inter-frame timing and the response timeout; it does not change the function code selected by the MODE parameter. A slave that does not implement FC05 will still reject the request when Compatibility Mode is on.
Can I use MODE=2 with DATA_LEN=1 instead of MODE=1 for every single-bit write?
Yes. The PDU sent on the wire is a Write Multiple Coils request with quantity=1. The slave parses it, writes the single bit, and returns a normal response. This is the recommended replacement for MODE=1 when the slave's FC05 implementation is buggy or absent.
Which firmware version of CP 1541-1 supports the full MODE 0..14 range?
CP 1541-1 (6GK7541-1AX00-0XE0) supports the full MODE range from firmware V2.0.0 onward. Earlier firmware limits the supported MODEs to 0..7. The TIA Portal Help entry "Modbus_Comm_Load / Modbus_Master" lists the exact firmware dependency for each MODE. Update the module's firmware with the Siemens support tool before assuming a MODE is unavailable.
My S7-1500 master fails with STATUS 0x0003 when writing a coil. Is that the same problem?
No. STATUS 0x0003 means the data pointer (DATA_PTR) points outside the configured data block, the data block is optimized, or the data block number does not exist. Re-allocate the data block as a non-optimized DB and confirm the DB number exists at runtime. See the MODBUS (RTU) (S7-1200, S7-1500) error reference for the full list of causes.
Why does LEN=2 work with MODE=1 on some slaves but is not recommended?
Some legacy slaves have a guard in their FC15 handler that tolerates FC05 requests with LEN>1 by misrouting them to the FC15 parser. This is non-conformant and depends on the slave's specific firmware behavior. The S7 master does not deliberately downgrade MODE=1 to FC15; the slave is taking liberties with the protocol. Do not rely on this. Use MODE=2 with DATA_LEN=1 for a portable, spec-compliant fix.