What They Are
A Modbus function code is the operation byte that tells the server what to do with the request. It defines whether the request reads or writes data and which register family is being accessed.
If the wrong function code is used for the expected data type, the device can respond with an exception even though transport and addressing are otherwise correct.
Within Modbus, function codes are the line between “the link is up” and “the request actually matches the device model.” The client can have the right IP address, serial settings, and register offset and still fail if the request asks for the wrong data family or unsupported write behavior.
That is equally true on Modbus RTU and Modbus TCP. The transport changes how the request gets there, but not which operation byte the server expects for coils, discrete inputs, input registers, or holding registers.
Common Public Function Codes
| Code | Name | Typical Data Family | Access |
|---|---|---|---|
01 | Read Coils | Modbus Coils | Read |
02 | Read Discrete Inputs | Modbus Discrete Inputs | Read |
03 | Read Holding Registers | Modbus Holding Registers | Read |
04 | Read Input Registers | Modbus Input Registers | Read |
05 | Write Single Coil | Modbus Coils | Write |
06 | Write Single Register | Modbus Holding Registers | Write |
15 | Write Multiple Coils | Coils | Write |
16 | Write Multiple Registers | Holding Registers | Write |
23 | Read/Write Multiple Registers | Holding registers | Combined read/write |
Register Family Mapping
| Register Family | Read Function Code | Write Function Code |
|---|---|---|
| Modbus Coils | 01 | 05, 15 |
| Modbus Discrete Inputs | 02 | None |
| Modbus Input Registers | 04 | None |
| Modbus Holding Registers | 03 | 06, 16 |
Why Function-Code Mismatch Happens
| Failure Pattern | What Usually Happened | Practical Result |
|---|---|---|
| Wrong data family assumption | A holding register was treated like an input register, or a status bit was treated like a coil | The device returns an exception or wrong data |
| Write path assumed too broadly | The device supports reads but not the requested write behavior | Reads work while writes fail |
| Device profile is narrower than the generic spec | The protocol manual or firmware supports only a subset of public operations | The request is valid Modbus in theory but not on that product |
| Gateway configuration used the wrong operation | The point type and function code drifted apart during mapping | Commissioning looks like an addressing error when it is actually an operation mismatch |
Exception Behavior
If a device rejects the request, it returns an exception response with the function code flagged and an exception code explaining the failure.
| Exception Code | Meaning | Common Real-World Cause |
|---|---|---|
01 | Illegal Function | Wrong function code for the device or register family |
02 | Illegal Data Address | Wrong address or off-by-one mapping |
03 | Illegal Data Value | Value out of valid range |
04 | Server Device Failure | Internal device-side failure |
Commissioning Notes
Function-code validation works best when it is tied to one known-good point in each data family the project actually uses. For example, confirm one coil, one input register, and one holding register before scaling up the full point list. That quickly separates transport health from data-family or write-path mistakes.