Modbus Protocol

5 min read Last updated Fri Jun 12 2026 08:40:30 GMT+0000 (Coordinated Universal Time)

A serial communication protocol for industrial devices. Developed by Modicon in 1979. Widely used in SCADA systems, PLCs, and IoT edge layers.

Follows master-slave architecture:

  • Master
    Initiates all communication. Only 1 master exists on a bus at a time. Sends requests and waits for responses.
  • Slave
    Responds only when addressed. Each slave has a unique 8-bit device address (1–247). Address 0 is reserved for broadcast; slaves do not respond to it. 248 Up to 247 slaves may respond. Never communicate spontaneously.

Modbus appears primarily at the edge layer, connecting sensors, PLCs, meters, and actuators to a local controller. The gateway aggregates this data and forwards it via MQTT or similar protocols to the cloud. Modbus TCP enables direct integration of industrial devices into Ethernet-based IoT architectures.

Data Model

4 register/coil tables, each with 65,536 addressable locations (16-bit address):

  • Coils
    1-bit, read/write. Represents discrete outputs such as relays and valves.
  • Discrete inputs
    1-bit, read-only. Represents discrete inputs such as switches and sensors.
  • Input registers
    16-bit, read-only. Analogue input values.
  • Holding registers
    16-bit, read/write. General-purpose configuration and data storage.

Packet Structure

All variants share the same Protocol Data Unit (PDU):

Function Code 1 byte Data N bytes

The PDU is wrapped in a variant-specific Application Data Unit (ADU) that adds addressing and error checking.

Function Codes

Every request contains a 1-byte function code specifying the operation:

CodeOperation
01Read coils
02Read discrete inputs
03Read holding registers
04Read input registers
05Write single coil
06Write single register
15Write multiple coils
16Write multiple registers

If a slave cannot execute a request, it responds with an exception: the function code OR-ed with 0x80, followed by a 1-byte error code.

Variants

Modbus RTU

Binary encoding over RS-232 or RS-485. Most compact variant. CRC-16 error checking.

Slave Address 1 byte PDU 1+N bytes CRC 2 bytes
  • CRC
    CRC-16, low byte transmitted first.
  • Frame boundaries
    No start/end delimiters. A silent interval of at least 3.5 character times marks frame start and end.
  • Size
    Minimum 4 bytes (address + function code + CRC, no data). Maximum 256 bytes (1 + 1 + 252 data + 2 CRC).

Typically runs over RS-485: differential signalling, up to 247 devices, bus length up to ~1200 m.

Modbus ASCII

Each binary byte encoded as 2 ASCII hex characters. Longer frames than RTU but human-readable. LRC error checking.

Start 1 ch Address 2 chars PDU 2+2N chars LRC 2 ch End 2 chars
  • Start
    : (ASCII 0x3A).
  • End
    CR LF (0x0D 0x0A).
  • LRC
    Two’s complement of the sum of all byte values from Address through Data. Encoded as 2 ASCII hex chars.
  • Size
    Minimum 9 characters. Maximum 513 characters (1 start + 2 address + 2 function + 504 data + 2 LRC + 2 CRLF). Each RTU data byte becomes 2 chars, so ASCII frames are approximately twice the size of an equivalent RTU frame.

Modbus TCP

Modbus PDU over TCP/IP on port 502. No CRC; TCP handles error checking. IP addressing removes the 247-device limit.

The PDU is prefixed with a 7-byte MBAP header:

Transaction ID 2 bytes Protocol ID 2 bytes Length 2 bytes Unit ID 1 byte PDU 1+N bytes
  • Transaction ID
    Echoed in the response. Matches request/response pairs when requests are pipelined.
  • Protocol ID
    Always 0x0000.
  • Length
    Byte count of everything that follows (Unit ID + PDU).
  • Unit ID
    Slave address. Used when a TCP gateway fronts a serial Modbus network.
  • Size
    Minimum 8 bytes (7 MBAP + 1 function code, no data). Maximum 260 bytes (7 MBAP + 1 function code + 252 data).

Limitations

  • No built-in authentication or encryption. Sensitive deployments must apply security at the network layer.
  • Request-response only. Slaves cannot push data; the master must poll.
  • 16-bit register width requires device-level conventions for wider data types.
Was this helpful?