2026-06-12 · Modbus · fieldbus · RS-485 · embedded

Modbus from the wire up: ASCII vs RTU vs TCP

Modbus was published by Modicon in 1979 to talk to PLCs, and almost half a century later it is still the first protocol you meet on a factory floor. The reason is brutal simplicity: a master asks, a slave answers, and everything on the wire fits in a frame you can decode by eye. No stack, no licensing, no surprises — which is exactly why every VFD, energy meter, temperature controller and PLC still ships with it.

This post walks through the three variants — ASCII, RTU and TCP — at the byte level, then looks at which physical interfaces can actually carry them.

One protocol, one data model

Before the framing differences, the part that never changes. Modbus is a request/response protocol with a single master (client) and up to 247 addressable slaves (servers). All data lives in four tables:

TableAccessSizeTypical use
Coilsread/write1 bitrelay outputs, run/stop bits
Discrete inputsread-only1 bitlimit switches, status bits
Holding registersread/write16 bitsetpoints, configuration
Input registersread-only16 bitmeasurements, counters

A handful of function codes cover nearly all real traffic: 01/02 read bits, 03/04 read registers, 05/06 write a single bit/register, 15/16 write multiple. The function code plus its data is called the PDU — and the PDU is identical in ASCII, RTU and TCP. The variants differ only in what gets wrapped around it.

Typical Modbus network: a SCADA client talks Modbus TCP to a PLC/gateway, which is the RTU master of an RS-485 segment carrying a VFD, an I/O module and a temperature controller, with 120 ohm termination at both ends. Figure 1 — The classic plant topology: TCP at the top for SCADA, one RS-485 RTU segment at the bottom doing the real work.

The three framings

Frame anatomy of Modbus ASCII, RTU and TCP: ASCII wraps hex characters between a colon and CRLF with an LRC; RTU is raw binary delimited by 3.5 character silences with a CRC-16; TCP prepends a 7-byte MBAP header and drops the checksum entirely. Figure 2 — Same PDU, three different envelopes. Note what each variant uses to find the frame boundary: characters (ASCII), silence (RTU), a length field (TCP).

RTU — the workhorse

RTU sends raw binary: one address byte, the PDU, and a CRC-16. Nothing marks the start or end of a frame — the frame boundary is silence. The spec requires at least 3.5 character times of idle line between frames (t₃.₅), and any gap longer than 1.5 character times (t₁.₅) inside a frame makes it invalid. With the standard 8E1 format one character is 11 bits, so:

Baud rate1 chart₁.₅t₃.₅
96001.146 ms1.72 ms4.01 ms
192000.573 ms0.86 ms2.005 ms
> 192000.75 ms (fixed)1.75 ms (fixed)

Above 19200 baud the spec freezes the timers at 750 µs / 1.75 ms because the proportional values get impractically tight. This timing rule is also RTU’s sharp edge: an OS-buffered USB–RS-485 converter that pauses mid-frame will silently break framing — more on that at the end.

ASCII — the debuggable one

ASCII takes every binary byte and sends it as two hexadecimal characters, framed between a : and a CR LF, protected by a simple LRC (two’s complement of the byte sum). The result is twice the bytes on the wire, but two real advantages: you can read a frame in any terminal program, and timing doesn’t matter — gaps of up to a second between characters are legal. On a radio modem or any link with unsteady latency, ASCII survives where RTU framing falls apart.

TCP — the same PDU in an Ethernet suit

Modbus TCP keeps the PDU and replaces everything else. A 7-byte MBAP header carries a transaction ID (so responses can be matched to requests — several may be in flight at once), a protocol ID (always 0), a byte-count length field, and a unit ID (the old slave address, still used when a gateway forwards to a serial segment behind it). There is no checksum — TCP’s own integrity checking covers it. The well-known port is 502.

Two structural differences matter in practice. First, the serial variants allow exactly one outstanding request on the bus; TCP allows many, from many clients concurrently. Second, TCP has no broadcast — serial address 0 (broadcast write) simply doesn’t translate.

One transaction under the microscope

The classic example: read 3 holding registers starting at 0x006B (register 40108) from slave 0x11.

Byte-level analysis of a function code 03 transaction: the 8-byte RTU request with address, function, start, quantity and CRC fields annotated; the 11-byte response carrying three big-endian register values; and the same request re-framed as ASCII text and as a Modbus TCP packet with MBAP header. Figure 3 — One read transaction in all three framings. The six PDU bytes 03 00 6B 00 03 (plus address) never change — only the wrapper does.

Worth noticing in the response: register contents are big-endian — high byte first. The CRC, in a small act of cruelty, goes low byte first. Mixing those two up is a rite of passage.

The 17-character ASCII version of the same request makes the cost visible: 8 binary bytes became 17 on the wire. That’s the price of debuggability.

Which wire can carry Modbus?

The spec deliberately says nothing about voltage levels. Serial Modbus needs nothing more than a UART, so it runs over anything a UART can drive:

Protocol stack diagram: the Modbus PDU sits on top; the serial line frame (address + CRC) goes through a UART onto TTL, RS-232 or RS-485 electrical layers; the MBAP-framed variant goes through TCP port 502 onto Ethernet, IP or Wi-Fi. Figure 4 — Modbus is physical-layer agnostic. The PDU survives every hop; gateways only swap the wrapper.

  • TTL/CMOS UART — two MCUs on the same board can speak Modbus RTU directly. Handy when one of them is a third-party module that already exposes Modbus.
  • RS-232 — point-to-point only, one device, ~15 m. Fine for a config port; wrong for a plant.
  • RS-485 — the de-facto standard carrier. Differential pair, multidrop (32 unit loads per segment, more with modern fractional-load transceivers), 1200 m at moderate baud rates, excellent noise immunity. Half-duplex two-wire is the common wiring; the master must manage driver-enable turnaround.
  • RS-422 — four-wire full duplex, one driver / multiple receivers; you meet it in legacy installations.
  • Ethernet / Wi-Fi — Modbus TCP. Anything that moves TCP moves it.

The default serial character format is 8E1 (even parity). 8N2 is the specified fallback; plain 8N1 is everywhere in the field but technically off-spec — a classic source of “it works with my USB dongle but not with the PLC” tickets.

Choosing between them

ASCIIRTUTCP
Encodinghex textbinarybinary
Frame overhead~2.2× RTUsmallest+7 B MBAP
Framing by: … CR LF3.5 char silencelength field
Error checkLRC (weak)CRC-16 (strong)TCP layer
Timing sensitivitynonestrictnone
Concurrent requests11many
Best atflaky links, debuggingthe standard fieldbusSCADA, IT integration

Practical rule: RTU on the wire, TCP above it. RTU owns the device-level segments because it’s the smallest frame with the strongest checksum; TCP owns everything that touches a network. ASCII is the niche tool you’re glad exists the day you must tunnel Modbus through a half-duplex radio with 300 ms of jitter.

Field notes — where Modbus bites

  • The off-by-one address. Register “40108” is addressed as 0x006B (107). The 4xxxx convention is 1-based documentation notation, the wire is 0-based. Every integrator has lost an afternoon to this.
  • 32-bit values. Two consecutive registers, and the standard doesn’t define the word order. Vendors split roughly 50/50 between big- and little-word-endian; good masters have a “word swap” checkbox for a reason.
  • Exception responses. A slave that can’t honor a request answers with the function code ORed with 0x80 and one exception byte (0x02 = illegal address, 0x03 = illegal value…). If your driver treats that as a timeout instead of parsing it, debugging becomes archaeology.
  • USB converter buffering. A USB–RS-485 dongle hands data to the OS in 1 ms+ chunks; at high baud rates that pause exceeds t₁.₅ and shatters RTU frames. Converters with hardware buffering — or just dropping to 19200 — fix mysteries that look like “random CRC errors.”
  • Driver-enable turnaround. On two-wire RS-485 the master must release the bus fast after the last stop bit, and claim it again fast enough for the reply. Transceivers with automatic direction control remove a whole class of races.
  • Security is not a feature. Modbus has no authentication and no encryption — anyone on the network can write any register. Modbus TCP must live in a segmented OT network or behind a gateway; “we put the PLC on the office LAN” is an incident report waiting for its date field.