Modbus RTU Frame Builder & Decoder

Build and decode Modbus RTU frames with automatic CRC, function-code reference and error decoding.

Example: 03 — Read Holding Registers from slave 1: 01 03 00 00 00 0A C5 CD

Check it against real silicon

Chiprun runs your firmware on an emulated microcontroller and hands back the UART output, so you can confirm these numbers rather than trusting them.

Chiprun docs

Formula

address · function · data · CRC-16/MODBUS (low byte first)

Calculations follow Modbus over Serial Line V1.02.

Worked example

03 — Read Holding Registers from slave 1: 01 03 00 00 00 0A C5 CD

  1. payload = address · function · start · quantity

    01 03 00 00 00 0A

    6 bytes

  2. CRC-16/MODBUS over the payload

    poly 0x8005, init 0xFFFF, reflected

    0xCDC5

  3. append CRC low byte, then high byte

    … C5 CD

    01 03 00 00 00 0A C5 CD

    Reversed relative to every other field in the protocol.

Frequently asked questions

Why is the Modbus CRC sent low byte first?

A historical quirk of the specification. Every other multi-byte field — addresses, register values, quantities — is big-endian, but the CRC alone is little-endian. A frame that fails only on the CRC is very often correct apart from that reversal.

Why does my register address seem off by one?

Two conventions. Documentation typically numbers holding registers from 40001, while the wire protocol numbers them from 0. Register 40001 in a manual is address 0x0000 in the frame. Reading the wrong register by exactly one is the classic symptom.

What does an exception response look like?

The function code comes back with its high bit set — a request for function 03 returns 0x83 — followed by a single exception code. Code 2 means illegal data address, which usually means the off-by-one above; code 3 means illegal data value.

How does a slave know where a frame ends?

Silence. Modbus RTU has no framing bytes; a gap of at least 3.5 character times marks the boundary. That is why RTU is sensitive to timing, and why a busy operating system between you and the serial port can break it in ways a scope trace looks fine for.

Related tools