Modbus RTU
The factory-floor classic: address, function code, data, CRC, over RS-485.
Request: read two registers
The master asks slave 1 for two holding registers. The CRC is computed for real; step through each field.
Whole frame
8 bytes: 01 03 00 00 00 02 C4 0B. No start/end markers: the frame is delimited by silence of at least 3.5 character times before and after it.
| Field | Offset | Example value | Meaning |
|---|---|---|---|
| Slave address | Byte 0 | 0x01 = 1 | Which device should answer: 1–247 (0 is broadcast, nobody replies). Every device on the RS-485 pair hears the frame; only address 1 acts on it. |
| Function code | Byte 1 | 0x03 = Read Holding Registers | What to do. 0x03 = Read Holding Registers. Others: 0x01 read coils, 0x04 read input registers, 0x06 write one register, 0x10 write many registers. |
| Starting address | Byte 2–3 | 0x0000 = register 0 (documented as 40001) | The first register to read, counted from 0 on the wire. Documentation often prints it as 40001 (the 4xxxx range means holding registers), which is address 0 here. |
| Quantity | Byte 4–5 | 2 registers | How many consecutive 16-bit registers to read: 1–125. |
| CRC-16 | Byte 6–7 | 0x0BC4 (sent low byte first) | A CRC-16 over every byte before it (initial value 0xFFFF, polynomial 0xA001). Quirk: it is sent low byte first, so the value 0x0BC4 appears as C4 0B on the wire. A receiver that computes a different CRC discards the frame silently. |
Overview
Modbus (1979) is the lingua franca of industrial devices: power meters, inverters, temperature controllers, PLCs. The RTU variant sends compact binary frames over a serial line, usually RS-485 so many slaves can share one twisted pair over hundreds of metres.
A master polls; slaves only answer. Data lives in numbered 16-bit registers, so 'reading the temperature' means reading register N. There is no frame marker: a pause of 3.5 character times separates frames, and a CRC proves the content.
Key facts
- Physical layer
- RS-485 (or RS-232)
- Framing
- UART, 8E1 or 8N2 typical
- Typical speeds
- 9600 / 19200 baud
- Addresses
- 1 – 247
- Max frame
- 256 bytes
- Error check
- CRC-16 (low byte first)
Response
The slave echoes address and function, says how many bytes follow, and returns the values.
Whole frame
9 bytes: 01 03 04 00 0A 00 14 DA 3E. The slave answers only when asked; it never speaks first.
| Field | Offset | Example value | Meaning |
|---|---|---|---|
| Slave address | Byte 0 | 0x01 = 1 | The responder echoes its own address so the master knows who is speaking. |
| Function code | Byte 1 | 0x03 | Echoed from the request. If something went wrong, the slave sets the top bit (0x83) and sends an exception instead. |
| Byte count | Byte 2 | 4 | How many data bytes follow: 2 registers × 2 bytes = 4. |
| Register 0 | Byte 3–4 | 0x000A = 10 | Value of register 0, big-endian (high byte first). Say it is a temperature in tenths of a degree: 10 = 1.0 °C. |
| Register 1 | Byte 5–6 | 0x0014 = 20 | Value of register 1, big-endian: 0x0014 = 20. |
| CRC-16 | Byte 7–8 | 0x3EDA (sent low byte first) | A CRC-16 over every byte before it (initial value 0xFFFF, polynomial 0xA001). Quirk: it is sent low byte first, so the value 0x3EDA appears as DA 3E on the wire. A receiver that computes a different CRC discards the frame silently. |
When something goes wrong
An error reply is only five bytes. The top bit of the function code is the flag.
Whole frame
An error is a 5-byte frame: the function code with its top bit set, then a one-byte reason.
| Field | Offset | Example value | Meaning |
|---|---|---|---|
| Slave address | Byte 0 | 0x01 | Same slave answering. |
| Function code + 0x80 | Byte 1 | 0x83 = 0x03 | 0x80 | 0x03 with the top bit set = 0x83. That single bit is how the master tells an error from a normal reply. |
| Exception code | Byte 2 | 0x02 = Illegal Data Address | Why it failed. 0x01 illegal function, 0x02 illegal data address (the register does not exist), 0x03 illegal data value, 0x04 device failure. |
| CRC-16 | Byte 3–4 | 0xF1C0 (sent low byte first) | A CRC-16 over every byte before it (initial value 0xFFFF, polynomial 0xA001). Quirk: it is sent low byte first, so the value 0xF1C0 appears as C0 F1 on the wire. A receiver that computes a different CRC discards the frame silently. |
One poll cycle
Turn-taking on a single shared pair.
Whole exchange
Strict master/slave: the master asks, one slave answers, the line goes quiet. All timing is decided by silence on the wire.
1Master asks
The master sends the 8-byte request on the shared RS-485 pair. Every slave hears it, but only the one whose address matches processes it. The others wait out the frame.
2Slave answers
After at least 3.5 character times of silence, the slave sends its 9-byte reply. Master and slaves take turns on the single pair: the half-duplex line is never driven by two at once.
Where you meet it
- Energy meters, solar inverters, heat pumps
- PLCs, temperature controllers, motor drives
- Modbus TCP wraps the same function codes in a TCP packet (no CRC, a 7-byte header instead)
Watch out for
- Register numbering is a mess: 40001 in the manual is address 0 on the wire. Check whether your tool is 0-based or 1-based.
- The CRC goes out low byte first, while all register data goes out high byte first.
- RS-485 needs termination (120 Ω) and biasing at the ends of the line, and the direction pin on the transceiver must be switched fast enough.
Standards
- Modbus Application Protocol Specification V1.1b3
- Modbus over Serial Line Specification V1.02