FirmGod

Modbus RTU Frame Builder & Parser

Decode a captured Modbus RTU frame field by field, or build a request from a function code and address. Exception responses and CRC errors are called out.

Paste straight from a serial sniffer. Separators and 0x prefixes are ignored.

Samples:

CRC valid

Slave 1, function 3 (Read Holding Registers)

FieldBytesMeaning
Slave address011
Function code033 — Read Holding Registers
Start address00 000 (0x0000)
Quantity00 0A10
CRC-16 (low byte first)C5 CD0xCDC5 — valid

The structure of an RTU frame

Every Modbus RTU frame has the same shape: a one-byte slave address, a one-byte function code, a variable data section, and a two-byte CRC. There is no length field and no start delimiter. Frames are separated by silence on the line — at least 3.5 character times — which is why RTU is sensitive to timing and why USB serial adapters with large buffers sometimes cause trouble.

FieldSizeNotes
Slave address1 byte1–247; 0 is a broadcast that gets no reply
Function code1 byteHigh bit set marks an exception response
Data0–252 bytesLayout depends on the function and direction
CRC-162 bytesLow byte first, unlike every other field

Function codes you will actually meet

CodeNameOperates on
0x01Read CoilsWritable single bits
0x02Read Discrete InputsRead-only single bits
0x03Read Holding RegistersWritable 16-bit registers
0x04Read Input RegistersRead-only 16-bit registers
0x05Write Single Coil0xFF00 for on, 0x0000 for off
0x06Write Single RegisterOne 16-bit value
0x0FWrite Multiple CoilsBits packed low bit first
0x10Write Multiple RegistersPreceded by a byte count

Functions 0x03 and 0x04 are the ones that cause the most confusion, because many devices expose the same physical data through both, and documentation is often unclear about which one a given register map uses. If a read returns an illegal data address exception, trying the other function code is a reasonable next step.

Exception responses

When a device understands a frame but cannot serve it, it replies with the function code plus 0x80 and one exception byte. The three you will see in practice:

  • 0x01 Illegal Function — the device does not implement that function code at all.
  • 0x02 Illegal Data Address — the register does not exist, or the requested range runs past the end of a block. Check the 40001 offset before assuming the map is wrong.
  • 0x03 Illegal Data Value — the value is outside the range the device accepts, or the quantity field is invalid. Note that this refers to the value in the request, not to a value stored in the device.

Debugging a link that does not respond

Silence carries no diagnostic information, so work through the layers in order. Confirm the CRC on the frame you are sending. Confirm the slave address matches the device, since many default to 1 but plenty ship with something else. Confirm baud rate, parity, and stop bits — RTU commonly runs 8E1, and a mismatch on parity alone produces framing errors that look identical to a dead device. Only then start questioning the register map.

Frequently asked questions

How do I tell a request from a response?

A frame does not label itself. For read functions, a request always has exactly four data bytes (address and quantity), while a response starts with a byte count. This tool infers the direction from the length the same way a protocol analyser does.

What does a function code with the high bit set mean?

It is an exception response. The device takes the original function code, adds 0x80, and follows it with a single exception code. Function 0x83 is an error reply to a read holding registers request.

What causes exception code 2, illegal data address?

The requested register does not exist on that device, or the request crosses the end of a valid block. It is frequently an off-by-one from the 40001-style documentation offset rather than a genuinely wrong address.

Why does my device not reply at all?

Silence usually means the frame never passed validation. A bad CRC, a wrong slave address, or a broken inter-frame gap all cause the device to discard the frame without an error. Paste the frame above to check the CRC first.