Table of Contents
ToggleEvery Modbus message carries one small number that tells the slave exactly what to do, read or write, bits or registers. Learn those few numbers and you can read any Modbus map, build any request and decode almost any communication fault.
A Modbus master and slave talk using a short list of numbered commands. Once you understand what each of the main Modbus function codes reads or writes, register maps, gateway settings and error messages start to make sense.

What Are Modbus Function Codes?
Modbus function codes are one byte numbers inside every Modbus request that tell the slave device which action to perform, such as reading coils, reading holding registers or writing a value. The same codes are used on serial Modbus RTU and on Modbus TCP, as compared in Modbus RTU vs Modbus TCP.
The protocol itself is explained in Modbus protocol explained, but day to day field work depends mostly on eight public codes. They read and write four data tables, coils, discrete inputs, input registers and holding registers.

On a serial network, one master polls up to 247 slaves over a twisted pair, so correct wiring and RS485 termination and biasing come first. After that, every successful poll depends on choosing the right code and address.
How a Modbus Request and Response Works
The protocol data unit, or PDU, is the function code followed by its data. The Modbus Application Protocol Specification V1.1b3 limits the serial PDU to 253 bytes, since a 256 byte RTU frame also carries a 1 byte address and a 2 byte CRC.
In RTU mode, frames are separated by a silent gap of at least 3.5 character times, which depends on the baud rate covered in UART frame and baud rate. Modbus TCP replaces the address and CRC with a 7 byte MBAP header and normally uses port 502.
The Modbus specification reserves function codes 65 to 72 and 100 to 110 for user defined functions. Vendors can add private commands there without clashing with the public codes.
8 Essential Modbus Function Codes at a Glance
| Code | Hex | Name | Data Table | Max per Request |
|---|---|---|---|---|
| 01 | 0x01 | Read Coils | Coils, read and write bits | 2000 bits |
| 02 | 0x02 | Read Discrete Inputs | Discrete inputs, read only bits | 2000 bits |
| 03 | 0x03 | Read Holding Registers | Holding registers, 16 bit | 125 registers |
| 04 | 0x04 | Read Input Registers | Input registers, read only 16 bit | 125 registers |
| 05 | 0x05 | Write Single Coil | One coil | 1 bit |
| 06 | 0x06 | Write Single Register | One holding register | 1 register |
| 15 | 0x0F | Write Multiple Coils | Several coils | 1968 bits |
| 16 | 0x10 | Write Multiple Registers | Several holding registers | 123 registers |
The limits in the last column come from the Modbus Application Protocol Specification and keep every frame within 253 bytes of PDU.
Read Modbus Function Codes 01, 02, 03 and 04
Reads the on or off state of output bits that can also be written.
Reads input bits that only the slave can change.
Reads 16 bit registers that can also be written.
Reads 16 bit registers that only the slave can change.
Bit replies are packed eight to a byte, starting from the lowest address in the least significant bit. Register replies return two bytes per register, high byte first, and their meaning depends on the PLC data types defined in the slave register map.
If a meter manual lists a value at 30001, use FC 04, and if it lists 40001, use FC 03. When the manual gives only an offset, check which Modbus function codes it names before guessing.
Write Modbus Function Codes 05, 06, 15 and 16
FC 05 writes one coil, where the value FF00 hex means ON and 0000 hex means OFF, as stated in the specification. Any other value is rejected, which is a common trap when a SCADA driver sends 0001 for ON.
FC 06 writes one 16 bit holding register, and a normal reply simply echoes the request. FC 15 writes a block of coils and FC 16 writes a block of registers, and both replies return only the start address and quantity written.
A 32 bit float or long value needs two registers, so it must be written with FC 16 in one frame rather than two FC 06 frames. Writing the halves separately can briefly leave a wrong value, which is risky for a setpoint read by a PLC MSG instruction or a drive.
Modbus function codes are not limited to data access, since FC 08 runs serial line diagnostics and FC 43 with MEI type 14 reads the device identification. Most field engineers still use only the eight codes in this guide.
Register Addressing: 40001 Versus Offset
Documentation often shows register numbers such as 40001, while the frame carries a zero based offset. The leading digit names the table, so 0xxxx means coils, 1xxxx discrete inputs, 3xxxx input registers and 4xxxx holding registers, much like the address areas in PLC memory addressing.
Coils base = 1, Discrete inputs base = 10001
Input registers base = 30001, Holding registers base = 40001
Reply data bytes = 2 × quantity for registers, or quantity ÷ 8 rounded up for bits
RTU reply length = address + function + byte count + data + 2 byte CRC
Example:
Register 40108, quantity 3
Offset = 40108 minus 40001 = 107 = 006B hex
Data bytes = 2 × 3 = 6
RTU reply = 1 + 1 + 1 + 6 + 2 = 11 bytes
Some devices use six digit numbers such as 400001 to reach offsets above 9999, and some manuals are already zero based. If every value you read looks like the neighbour of the expected one, the map is probably off by one.
Register Offset and Reply Length Calculator
Worked Frame Example: FC 03 Read
Simply Modbus shows the request 11 03 006B 0003 7687 for reading three holding registers from slave 17. Here 11 hex is slave address 17, 03 is the function code, 006B is the start offset, 0003 is the quantity and 7687 is the CRC.
The same source explains that 006B hex equals 107, and 107 plus the 40001 base gives register 40108. The reply 11 03 06 AE41 5652 4340 49AD returns a byte count of 6, three register values and the CRC, exactly the 11 bytes our calculator predicts.
Second Worked Example: Writing a Float Setpoint
Suppose a flow computer needs a setpoint of 25.0 at holding registers 40201 and 40202 as an IEEE 754 float. The offset is 200, or 00C8 hex, the quantity is 2 and the byte count is 4, so the PDU is 10 00C8 0002 04 41C8 0000.
The float 25.0 is 41C80000 hex, split into high word 41C8 and low word 0000. If the device expects swapped word order, send 0000 41C8 instead, a choice usually set in the protocol gateway or driver.
Modbus Exception Codes and Their Meaning
When a slave understands a request but cannot carry it out, it replies with the function code plus 0x80 and a one byte exception code. A failed FC 03 read therefore comes back as 83 hex followed by the reason.
| Code | Name | Usual Field Cause |
|---|---|---|
| 01 | Illegal Function | Device does not support that function code |
| 02 | Illegal Data Address | Offset or quantity outside the register map |
| 03 | Illegal Data Value | Value out of range or bad quantity field |
| 04 | Server Device Failure | Internal fault while processing |
| 05 | Acknowledge | Long task accepted, poll again later |
| 06 | Server Device Busy | Slave busy with a long command |
| 0A hex | Gateway Path Unavailable | Gateway cannot route to the serial port |
| 0B hex | Gateway Target Failed to Respond | Serial slave behind gateway is silent |
No reply at all is different from an exception, because it points to wiring, baud rate, parity or slave address problems. These physical layer faults are covered in SCADA communication problems.
Troubleshooting Modbus Function Codes in the Field
- Confirm slave address, baud rate, parity and stop bits match on both ends.
- Check that the device supports the function code you are using.
- Convert the register number to a zero based offset and test one register first.
- Keep the quantity within the device limit, not just the protocol limit.
- Check byte and word order for 32 bit floats and long values.
- Use a Modbus test tool to compare raw hex frames with the manual.
- For Modbus TCP, verify the unit identifier and port 502 on the gateway.
Before blaming the PLC program, read one register with a laptop test tool connected directly at the device. If that works, the problem lies in the master configuration, not in the field device.
For long serial lines, compare RS232 and RS485 limits in differences between RS232 and RS485. Most panel faults in Indian plants turn out to be swapped A and B wires, a missing common or a wrong parity setting.
Advantages and Limitations of Modbus Function Codes
- Small, open and well documented code set.
- Same codes on serial RTU and Modbus TCP.
- Supported by almost every PLC, meter and drive.
- Easy to decode by eye in a hex frame.
- Only 16 bit registers, so floats need two registers.
- No standard data type or word order.
- Numbering differs between vendors, offset or 40001.
- No built in security in classic Modbus.
Where Modbus Function Codes Are Used Every Day
In a SCADA system, group neighbouring registers into one FC 03 block of up to 125 registers instead of many small polls. Good grouping starts with a clean SCADA tag database design and saves bandwidth on slow links to an RTU.
Modbus Application Protocol Specification PDF
Video Guide to Modbus Function Codes
Modbus Function Codes FAQ
They are one byte numbers in each Modbus request that tell the slave which action to perform. Typical actions are reading bits, reading registers or writing new values.
The eight common public codes are 01, 02, 03, 04, 05, 06, 15 and 16. Together they cover almost all routine reading and writing in plant automation work.
FC 03 reads holding registers, which a master can also write with FC 06 or FC 16. FC 04 reads input registers, which only the slave itself can change.
Many meters still place read only values in holding registers for convenience. Always follow the device register map rather than assuming the table from the value type.
The number 40001 is a documentation convention where the first digit names the holding register table. The frame itself carries only a zero based offset from the start of that table.
So register 40001 is sent as offset 0 and register 40108 as offset 107. Mixing these two styles is the most common cause of reading the wrong value.
The specification allows up to 125 registers in one FC 03 or FC 04 read. Writes with FC 16 allow up to 123 registers in one request.
Many field devices support much smaller blocks, sometimes only 32 or 64 registers. Check the device manual and reduce the block size whenever you receive exception 03 replies from the slave.
Exception 02 is Illegal Data Address, meaning the requested offset or range is outside the slave register map. It often appears when the master is off by one or reads past the last register.
Test a single known register first, then grow the block size step by step. Also confirm whether the manual numbers registers from 0 or from 1.
A float uses two consecutive 16 bit registers that together hold the IEEE 754 value. Read them with FC 03 and write them with FC 16 in one frame.
Devices differ in word order, so a value may appear as a huge or tiny number. Swap the two words in the driver setting until the reading matches the local display.
No, the function codes and data fields are identical in both versions of the protocol. Only the wrapping around the PDU changes from one transport to the other.
RTU adds a slave address and a CRC, while TCP adds a 7 byte MBAP header. A gateway therefore converts frames without altering the function code or the data.
Related Articles
- Modbus Protocol Explained
- Modbus RTU vs Modbus TCP
- RS485 Termination and Biasing Resistors
- Industrial Protocol Gateway
- SCADA Communication Problems
External References
- MODBUS Application Protocol Specification V1.1b3, Modbus Organization
- Read Holding Registers FC 03, Simply Modbus
- Modbus, Wikipedia
What We Learn Today
- Modbus function codes 01 to 04 read coils, discrete inputs, holding registers and input registers, while 05, 06, 15 and 16 write coils and registers.
- Register numbers such as 40108 are documentation labels, and the frame carries a zero based offset, so 40108 is sent as 107 or 006B hex.
- A slave that cannot execute a request replies with the function code plus 0x80 and an exception code, such as 02 for an illegal data address.
