Part II · Chapter 4
The Modbus Frame
A frame is one complete message as it appears on the wire: a definite string of bytes with a beginning, a middle, and an end. Its design is tidy: a small core that never changes, inside a thin wrapper that changes with the transport.
By the end of this chapter you can
- Separate any frame into its PDU (function code + data) and its ADU wrapper.
- Apply the big-endian rule to addresses, quantities, and register values.
- Explain the per-request limits, such as 125 registers, and build a request frame by hand.
So far requests and responses have been ideas. To send one, you must lay its parts out as bytes in a specific order. This chapter defines that layout. Learn the core once, learn the two wrappers, and you can read any Modbus frame.
The core: the protocol data unit
At the center of every Modbus message is the protocol data unit, or PDU. It has just two parts: a one-byte function code and a data field of zero or more bytes. The function code names the operation, exactly as in Part I. The data field carries whatever that operation needs: a starting address and quantity for a read, an address and value for a write, the returned values in a response.
The PDU is deliberately ignorant of how it will travel. It holds no device address and no error check; those belong to the wrapper. That's what lets the identical PDU ride a serial line one day and an Ethernet network the next. The PDU is capped at 253 bytes, a limit inherited from the earliest serial frames, and every transport respects it. It's the part you'll spend the most time reading, because it's where the meaning lives.
The wrapper: the application data unit
To deliver a PDU, a transport wraps it into an application data unit, or ADU. The ADU adds the two things a bare PDU lacks: a way to say which device the message concerns, and a way to check it arrived intact. In the classic serial form, that's a one-byte address in front and a two-byte error check behind: address, function code, data, error check.
Notice the clean separation: the PDU answers "what should happen"; the wrapper answers "to whom" and "did it arrive safely." The wrapper is thin, so Modbus overhead is tiny: just three extra bytes on a serial line. The largest serial ADU is therefore 256 bytes: 1 address byte + up to 253 PDU bytes + 2 error-check bytes. That number is why no single read can return unlimited data, as you'll see shortly.
Two wrappers, one core
Modbus TCP wraps the same PDU differently. Instead of an address byte and a trailing checksum, it puts a seven-byte header in front and adds no checksum, because the Ethernet and TCP layers already make sure data arrives correct and in order. That header, the MBAP header (dissected in Chapter 7), carries an identifier so a client can match responses to requests, a length, and the unit address. For now, the point is the symmetry: serial and TCP are two envelopes around one identical letter.
That's why the course can treat function codes (Chapter 8) separately from transports (Chapters 5–7). A "read holding registers" PDU is the same handful of bytes whether it arrives over RS-485 or Ethernet. Once you can build and read a PDU, switching transports means changing only the bytes around it, never the bytes inside it.
Byte order: most significant first
One rule about how numbers are laid out must be absorbed before you read any frame, because getting it wrong corrupts every multi-byte value. Modbus is big-endian: when a value needs more than one byte, the most significant byte is sent first. A register holding 0x1A2B travels as 1A then 2B. Addresses and quantities follow the same rule: a starting address of 100 (0x0064) is sent as 00 then 64.
"High byte first" is consistent throughout the core protocol, and it makes Modbus pleasant to read by hand: you meet the most significant part of every number first, just as you'd write it. Byte order only gets genuinely tricky when a device packs a value wider than sixteen bits across two registers, because then it must also decide which register comes first, and not all devices agree. That wrinkle gets its own treatment in Chapter 14. Within a single register, the rule is simply high byte first.
How big can a frame be?
Because the PDU is capped at 253 bytes, every operation has a natural ceiling on how much it can move in one request. The limits aren't arbitrary; they fall straight out of the frame size, and knowing them keeps you from sending a request the device must reject.
| Quantity | Limit per request |
|---|---|
| Read coils or discrete inputs | 2000 bits |
| Read holding or input registers | 125 registers |
| Write multiple coils | 1968 bits |
| Write multiple registers | 123 registers |
| PDU size (function + data) | 253 bytes |
| Serial ADU size (with address + CRC) | 256 bytes |
The one that surprises people is 125 registers per read. It follows from the byte budget of the response PDU, which must carry the function code, a byte count, and two bytes per register:
The write limit works the same way: a write-multiple-registers request spends 1 byte on the function code, 2 on the start address, 2 on the quantity, and 1 on the byte count, leaving 247 bytes, room for 123 registers. So if you need 300 registers from a device, you can't ask for them all at once: break the job into chunks of 125 or fewer and stitch the results together. Many client libraries do this for you, but knowing why the limit exists keeps the behavior from being a mystery.
A frame, byte by byte
Now make it concrete with the course's running example: a serial request to read four holding registers, starting at address 0, from unit 1. That's function code 0x03. Lay down the parts in order (address, function code, starting address, quantity) and append the error check:
| Bytes | Field | Meaning |
|---|---|---|
| 01 | Address | Unit address 1 |
| 03 | Function code | Read Holding Registers |
| 00 00 | Start address | Address 0 (big-endian) |
| 00 04 | Quantity | Read 4 registers (big-endian) |
| 44 09 | CRC | Error check (low byte first) |
Read left to right and the whole frame is 01 03 00 00 00 04 44 09: eight bytes. The middle five, 03 00 00 00 04, are the PDU. Strip the leading address and trailing CRC and that's exactly what would ride inside a TCP frame instead. Every field is where the rules say: the address selects the server, the function code names the operation, start and quantity are big-endian sixteen-bit numbers, and the CRC closes the frame. (The CRC itself is sent low byte first, the one exception to the big-endian rule; Chapter 5 explains why when it builds the CRC.)
Try it: RTU frame builder
You can now read the skeleton of any Modbus frame. What remains is the specifics of the serial wrapper: how that CRC is really computed, and the timing that marks where one frame ends and the next begins. That's Modbus RTU, the subject of Chapter 5.
Check your understanding
1. What does a PDU contain?
The PDU is just function code + data. The unit address and error check (or MBAP header) belong to the ADU wrapper.
2. A register holds 0x1A2B. In what order do its bytes go on the wire?
Modbus is big-endian: the most significant byte goes first, on every transport.
3. Why can one read return at most 125 registers?
The response PDU must fit in 253 bytes. After the function code and byte count, 251 bytes remain: 125 registers of 2 bytes each.
4. In the frame 01 03 00 00 00 04 44 09, which bytes would ride unchanged inside a Modbus TCP frame?
Strip the leading address (01) and trailing CRC (44 09). The PDU, 03 00 00 00 04, is identical in TCP.