# Modbus Frame Builder

> One page from jmrp.io, published as markdown. Index: https://jmrp.io/llms.txt

Canonical: https://jmrp.io/tools/modbus-frame-builder/
Language: en
Alternate: https://jmrp.io/es/tools/modbus-frame-builder/index.md
Updated: 2026-09-03
License: https://jmrp.io/license/
Category: embedded
Tags: modbus, rtu, tcp, industrial, plc, embedded, serial

Build and decode Modbus RTU/TCP/ASCII frames with CRC-16/LRC calculation, register interpretation, and byte visualization. Runs client-side.
Build-Date: 2026-09-06

Features:
- Builds Modbus RTU, TCP, and ASCII frames
- Auto CRC-16, LRC, and MBAP headers
- Decodes hex frames with exception detection
- Interprets registers with selectable byte order
- Runs fully client-side, no server

Questions answered:

**What is the difference between Modbus RTU and Modbus TCP frames?**

RTU frames are binary and end with a 16-bit CRC for serial lines, while TCP frames prepend a 7-byte MBAP header (transaction ID, protocol ID, length, unit ID) and drop the CRC because TCP/IP handles error checking. This tool builds and decodes both, plus Modbus ASCII with LRC.

**How is the Modbus RTU CRC-16 calculated?**

It uses the CRC-16 polynomial 0xA001 (the reflected form of 0x8005) computed over every byte except the CRC itself, then appended low byte first, high byte second. The tool calculates and validates it automatically when you build or decode a frame.

**Why do my 32-bit register values look wrong when decoded?**

Modbus registers are 16-bit, so 32-bit integers and floats span two registers and vendors disagree on the order. Try switching the byte order between Big-Endian, Little-Endian, Mid Big-Endian, and Mid Little-Endian in the data interpretation panel until the value matches your device.

**What does a Modbus exception response look like?**

The slave echoes the function code ORed with 0x80 followed by an exception code such as 01 (Illegal Function) or 02 (Illegal Data Address). Paste the frame into Decode mode and the tool flags the exception and names the error.

**Is my Modbus data sent to a server?**

No. All frame building, decoding, CRC/LRC calculation, and data interpretation run entirely in your browser; nothing is transmitted. The shareable link only encodes frame parameters in the URL query string.


---

**Interactive tool** — this page hosts the working application itself, not a description of one.

## About This Tool

Build valid Modbus RTU, TCP, and ASCII frames for embedded device
communication. The tool handles CRC-16 and LRC calculation, MBAP headers,
register value interpretation, response frame generation, and provides a
visual breakdown of each frame byte with color-coded segments.

### Features

- **Three protocols** — Modbus RTU (CRC-16), Modbus TCP (MBAP header), and Modbus ASCII (LRC)
- **11 function codes** — Read Coils (01), Read Discrete Inputs (02), Read Holding Registers (03), Read Input Registers (04), Write Single Coil (05), Write Single Register (06), Read Exception Status (07), Diagnostics (08), Write Multiple Coils (0F), Write Multiple Registers (10), Read/Write Multiple Registers (17)
- **Frame decoder** — paste hex frames to decode with auto-detect for RTU/TCP protocol, CRC/LRC validation, and exception response detection
- **Data interpretation** — decode register data as Unsigned Int 16, Signed Int 16, Unsigned Int 32, or Float 32 with byte order selection (Big-Endian, Little-Endian, Mid Big-Endian, Mid Little-Endian)
- **Response builder** — generate valid response frames for any function code, including exception responses with all standard exception codes
- **Data format helper** — enter decimal values and convert to hex bytes automatically, supporting uint16, int16, uint32, and float32
- **Address format toggle** — switch between 0-based, 1-based, and Modicon notation (4xxxx, 3xxxx) with automatic conversion
- **Common presets** — 8 quick-load frame examples for instant testing
- **Copy formats** — copy as hex with spaces, without spaces, C array, or Python bytes literal
- **Color-coded bytes** — visual breakdown with distinct colors for slave/unit, function code, data, CRC/LRC, protocol, and error segments
- **Share link** — shareable URL encoding the current frame configuration

### How do I use this tool?

#### Build Mode

1. Select **Build Frame** mode (default)
2. Choose the protocol (RTU, TCP, or ASCII)
3. Set the slave address, function code, start address, and quantity
4. For write functions, enter write data in hex or use the data format helper
  to enter decimal/float values
5. The frame is generated automatically with CRC-16 (RTU), MBAP header (TCP),
  or LRC (ASCII)
6. Copy the frame in your preferred format using the copy buttons

#### Decode Mode

1. Select **Decode Frame** mode
2. Choose the protocol or use **Auto-detect**
3. Paste a hex frame (e.g., `01 03 04 00 0A 00 64 B2 62`)
4. Click **Decode** or press Enter
5. Select the data interpretation format (uint16, int16, float32, etc.) to view
  register values

#### Response Builder

1. Select **Response Builder** mode
2. Choose the function code for the response
3. Enter the response data in hex bytes, or select **Exception Response** to build an error frame

### Modbus Protocol Overview

Modbus is a serial communication protocol developed by Modicon in 1979 for
industrial devices (PLCs, sensors, actuators). It follows a master/slave
architecture where the master initiates requests and slaves respond.

#### Frame Structures

| Protocol | Frame Structure | Error Check |
| --- | --- | --- |
| **RTU** | `[Slave] [FC] [Data...] [CRC Lo] [CRC Hi]` | CRC-16 |
| **TCP** | `[Transaction ID] [Protocol ID] [Length] [Unit ID] [FC] [Data...]` | TCP/IP |
| **ASCII** | `: [Slave] [FC] [Data...] [LRC] CR LF` | LRC |

### Function Codes Reference

| Code | Name | Data Type | Access |
| --- | --- | --- | --- |
| `01` | Read Coils | Discrete Output (1 bit) | Read |
| `02` | Read Discrete Inputs | Discrete Input (1 bit) | Read |
| `03` | Read Holding Registers | 16-bit Register | Read |
| `04` | Read Input Registers | 16-bit Register | Read |
| `05` | Write Single Coil | Discrete Output (1 bit) | Write |
| `06` | Write Single Register | 16-bit Register | Write |
| `07` | Read Exception Status | 8 coils (diagnostic) | Read |
| `08` | Diagnostics | Sub-function data | Read/Write |
| `0F` | Write Multiple Coils | Discrete Output (1 bit) | Write |
| `10` | Write Multiple Registers | 16-bit Register | Write |
| `17` | Read/Write Multiple Registers | 16-bit Register | Read/Write |

### Modicon Address Notation

Traditional Modbus documentation uses Modicon address ranges to identify data
types:

| Range | Data Type | Function Codes | Protocol Address |
| --- | --- | --- | --- |
| `00001–09999` | Coils (discrete output) | 01, 05, 0F | 0–9998 (0x0000–0x270E) |
| `10001–19999` | Discrete Inputs | 02 | 0–9998 (0x0000–0x270E) |
| `30001–39999` | Input Registers | 04 | 0–9998 (0x0000–0x270E) |
| `40001–49999` | Holding Registers | 03, 06, 10 | 0–9998 (0x0000–0x270E) |

### Exception Codes

When a slave cannot process a request, it returns an **exception response** with the function code ORed with `0x80` and an exception code:

| Code | Name | Description |
| --- | --- | --- |
| `01` | Illegal Function | Function code not supported by the slave |
| `02` | Illegal Data Address | Address not available on the slave device |
| `03` | Illegal Data Value | Value out of range for the slave |
| `04` | Slave Device Failure | Unrecoverable error on the slave |
| `05` | Acknowledge | Request accepted but processing takes time |
| `06` | Slave Device Busy | Slave is busy processing another request |
| `08` | Memory Parity Error | Extended file area parity check failed |
| `0A` | Gateway Path Unavailable | Gateway misconfigured or not available |
| `0B` | Gateway Target No Response | Target device did not respond to gateway |

### Byte Order (Endianness)

Modbus registers are 16-bit, but many devices store 32-bit values (integers,
floats) across two registers. The byte order varies by manufacturer:

| Name | Order | Example (Float 123.456) |
| --- | --- | --- |
| **Big-Endian (AB CD)** | Most common, Modbus standard | `42 F6 E9 79` |
| **Little-Endian (CD AB)** | Word-swapped | `E9 79 42 F6` |
| **Mid Big-Endian (BA DC)** | Byte-swapped | `F6 42 79 E9` |
| **Mid Little-Endian (DC BA)** | Full reversed | `79 E9 F6 42` |

### Is my Modbus data sent to a server?

All frame building, decoding, CRC/LRC calculation, and data interpretation
happens entirely in your browser. No Modbus data is transmitted to any server.
The shareable link only encodes frame parameters in URL query strings.

### Linux Command Reference

Common tools for testing Modbus communication from the command line:

#### Read Holding Registers with mbpoll

```bash
mbpoll -a 1 -r 0 -c 10 -t 4 /dev/ttyUSB0
```

**mbpoll Read Output**

```text
mbpoll 1.5 - FieldTalk(tm) Modbus(R) Master Simulator
Protocol configuration: Modbus RTU
Slave configuration: address = [1]
-- Polling slave 1...
[0]: 100
[1]: 200
[2]: 0
[3]: 1500
[4]: 0
```

#### Read Registers via TCP with modbus-cli

```bash
modbus read 192.168.1.100 %MW0 10
```

**modbus-cli Output**

```text
%MW0 = 100
%MW1 = 200
%MW2 = 0
%MW3 = 1500
```

#### Read Registers with pymodbus

```bash
python3 -c 'from pymodbus.client import ModbusTcpClient as C; c=C("192.168.1.100"); c.connect(); print(c.read_holding_registers(0,10,slave=1).registers)'
```

**pymodbus Output**

```text
[100, 200, 0, 1500, 0, 0, 0, 0, 0, 0]
```

#### Write Single Register with mbpoll

```bash
mbpoll -a 1 -r 0 -t 4 /dev/ttyUSB0 -- 100
```

**Output — Write Confirmation**

```text
mbpoll 1.5 - FieldTalk(tm) Modbus(R) Master Simulator
Written 1 reference(s).
```

#### Scan for Modbus Devices

```bash
for id in $(seq 1 247); do mbpoll -a $id -r 0 -c 1 -t 4 -1 /dev/ttyUSB0 2>/dev/null && echo "Device at $id"; done
```

**Output — Scan Results**

```text
Device at 1
Device at 5
```

### How is the CRC-16 calculated?

Modbus RTU uses CRC-16 with the polynomial `0xA001` (reflected form of `0x8005`). The CRC is calculated over all bytes in the frame except the CRC itself, and is appended in **little-endian** order (low byte first, high byte second).

### How is the LRC calculated?

Modbus ASCII uses a Longitudinal Redundancy Check. The LRC is the **two's complement** of the 8-bit sum of all bytes in the message (slave address through the last data byte). It is transmitted as two ASCII hex characters before the trailing CR LF.

