Modbus RTU vs TCP vs ASCIIModbus RTU / TCP / ASCII 对比

Same PDU, three envelopes.

同一个 PDU,三种信封。

PropertyRTUTCPASCII
Runs overRS-485 / RS-232 serialEthernet / IPRS-485 / RS-232 serial
Addressing1 byte unit ID in the frameUnit ID in MBAP, plus IP address1 byte unit ID in the frame
Headernone7-byte MBAP':' start character
ChecksumCRC-16, 2 bytesnone (TCP/IP checksums apply)LRC, 1 byte as 2 hex chars
Encodingbinarybinaryprintable ASCII hex
Max ADU256 bytes260 bytes513 characters
Frame delimiter3.5 character times of silenceMBAP length fieldCR LF
Typical useSensors, drives, meters on a busPLCs, gateways, SCADALegacy modems, low-quality links

RTU: address, PDU, CRCRTU:地址 + PDU + CRC

11 03 00 6B 00 03 76 87
└┬┘ └┬┘ └──┬──┘ └──┬──┘ └──┬─┘
 │   │     │       │       └──── CRC-16 (low byte first)
 │   │     │       └──────────── quantity
 │   │     └──────────────────── start address
 │   └────────────────────────── function code
 └────────────────────────────── unit ID

The only thing separating two frames is time: 3.5 character times of idle line. There is no length field and no start byte, so a device that starts listening mid-frame has no way to resynchronise — it must wait for the next gap. This is why tight polling loops can corrupt a bus that looks electrically perfect.

两帧之间唯一的边界是时间:3.5 个字符时间的空闲。没有长度字段也没有起始字节,中途开始接收的设备无法重新同步,只能等下一个间隔。这就是"电气上完美"的总线被过快的轮询打乱的原因。

TCP: transaction, length, unit, PDUTCP:事务号 + 长度 + 从站 + PDU

00 01 00 00 00 06 01 03 00 00 00 0A
└──┬─┘ └──┬─┘ └──┬─┘ └┬┘ └──┬──┘ └──┬──┘
   │      │      │    │     │       └─── PDU: read 10 registers at 0
   │      │      │    │     └─────────── function 03
   │      │      │    └───────────────── unit ID (matters behind a gateway)
   │      │      └────────────────────── length: unit + PDU = 6 bytes
   │      └───────────────────────────── protocol ID, always 0
   └──────────────────────────────────── transaction ID, echoed back

The MBAP header makes a byte stream self-delimiting: read the length, read that many bytes, done. That is why TCP tolerates arbitrary packet fragmentation while RTU depends on timing.

MBAP 头让字节流自带边界:读长度、按长度读、结束。所以 TCP 能容忍任意拆包,而 RTU 依赖时间间隔。

ASCII: two characters per byteASCII:每个字节两个字符

: 01 03 00 00 00 01 FB CR LF
│ └──────────┬──────────┘ └┬┘ └─┬─┘
│            │             │    └── terminator
│            │             └─────── LRC
│            └───────────────────── unit + PDU, as hex characters
└────────────────────────────────── start character

ASCII exists because some links cannot carry arbitrary binary — old modems, radio links, text-only multiplexers. It is exactly twice as long plus framing, so it is the slowest of the three. Its one advantage: a captured frame is readable in any terminal, and a human can compute the LRC by adding bytes.

ASCII 的存在是因为有些链路无法传输任意二进制——老式调制解调器、无线数传、只能过文本的复用器。它长度翻倍还多两字节,是三种里最慢的。唯一优点是抓到的帧在任何终端里都可读,人也能靠加法手算 LRC。

Which one should I use?该用哪一种?

What never changes between them三者之间不变的部分

The PDU — function code, address, quantity, data — is identical in all three. A register map is a register map: if a device answers exception 02 over RTU, it will answer exception 02 over TCP with the same address. When a protocol "works on RS-485 but not on Ethernet", the problem is in the gateway, the unit ID, or the addressing in your client — never in Modbus itself.

PDU——功能码、地址、数量、数据——三种完全一致。寄存器表就是寄存器表:设备在 RTU 上回异常码 02,换成 TCP 用同样地址还是异常码 02。遇到"RS-485 能用、以太网不能用",问题一定在网关、从站地址或客户端的寻址上,不在 Modbus 本身。