Modbus troubleshootingModbus 排错指南
Symptom, cause, fix.
现象、原因、解法。
Before anything else: confirm the four serial settings match the device exactly — baud rate, parity, data bits, stop bits. A wrong parity setting produces silence on some devices and garbage on others, and it looks exactly like a wiring fault.
先确认四件事:波特率、校验位、数据位、停止位与设备完全一致。校验位设错时,有的设备完全没反应,有的回一堆乱码,表现和接线故障一模一样。
1. Nothing comes back at all完全没有任何返回
Silence is not an exception — the device either never saw the frame or refused to answer it. Exceptions mean the device is alive, so if you get nothing, start at the wire.
"没有返回"和"回异常"是两回事。异常说明设备活着;完全没反应,先从物理层查。
- A and B swapped. RS-485 has no polarity protection. Swap the two data wires — it takes ten seconds and fixes a surprising share of cases.
- Unit ID mismatch. Try ID 1, then scan a range. A device configured for 247 will ignore everything addressed to 1, silently.
- Broadcast address. Unit 0 is broadcast: by specification every device acts on it and nobody answers. If you used 0, that is your answer.
- Half-duplex adapter direction. Cheap USB-RS485 dongles need RTS or automatic direction control. If the driver is wrong the adapter transmits but never listens.
- Wiring topology. RS-485 is a daisy chain, not a star. A star with long stubs reflects and garbles everything.
- Reference ground not connected. Two-wire RS-485 still needs a common ground reference on most transceivers; without it, long runs fail intermittently.
- Power. The device is not on, or is in a state where its serial stack is not running.
- A/B 接反。RS-485 没有极性保护,交换两根数据线试试——十秒钟的动作,能解决相当比例的现场问题。
- 从站地址不对。先试 1,再扫一段地址。地址是 247 的设备会静默忽略发往 1 的所有请求。
- 用了广播地址。地址 0 是广播:规范规定所有设备执行但谁都不许应答。填 0 就等于自问自答。
- 半双工方向控制。廉价 USB-RS485 靠 RTS 或自动方向控制,驱动不对时"发得出去、收不回来"。
- 拓扑。RS-485 必须手拉手串联,星形接法加长分支线会产生反射,把帧打烂。
- 参考地没接。两线制 RS-485 在多数收发器上仍需共地参考,不接时短距离正常、长距离间歇失败。
- 供电。设备没上电,或处于串口协议栈未运行的状态。
2. Bytes arrive but the CRC never matches有字节回来,但 CRC 永远不对
Garbage with a valid-looking length is electrical. Garbage with random lengths is usually a baud rate mismatch. Paste the bytes into the CRC calculator and look at the trace: if only the last two bytes are wrong, your link is fine and your checksum code is wrong.
长度正常但内容是乱码,通常是电气问题;长度都乱,多半是波特率不对。把字节粘进CRC 计算页看过程:如果只有末尾两字节不对,链路是好的,错在校验算法。
- Baud rate off by a factor (9600 vs 19200) — every byte is wrong.
- Parity mismatch — the device may answer with a parity error bit flipped, or nothing.
- Noise / no termination — occasional single-bit errors, worse with longer cable and higher baud.
- Wrong checksum variant — a frame with a plausible but incorrect CRC almost always means CRC-16/IBM was used instead of CRC-16/MODBUS, or the CRC bytes were included in the calculation.
- Byte order of the checksum — low byte first. Swapped, the frame is one swap from correct.
- 波特率差一档(9600 与 19200)——每个字节都是错的。
- 校验位不一致——可能整帧错位,也可能干脆不回。
- 干扰 / 没接终端电阻——偶发单比特错误,线越长、波特率越高越明显。
- 校验变体用错——CRC 看着像但永远不过,多半是用了 CRC-16/IBM,或者把 CRC 自己也算进去了。
- 校验字节顺序反了——低字节在前。反了的话,交换一下就对。
3. Exception 02 — illegal data address异常码 02——非法数据地址
The device is answering, so everything electrical is fine. It simply does not have a register there.
设备能应答,说明电气层没问题,只是那个地址它没有。
- Off by one. Manual says 40001, you sent 1. The protocol address is
40001 − 40001 = 0. - Wrong table. Reading a holding register that only exists as an input register (function 03 vs 04).
- Range past the end. Starting at the last register and asking for 10 more.
- 32-bit value counted as one. A float32 occupies two registers; reading only one leaves half of it behind, and writing one corrupts the pair.
- Device-specific hole. Many devices leave gaps in the map. Read one register at a time to find where it breaks.
- 差一位。手册写 40001,你发了 1。协议地址 =
40001 − 40001 = 0。 - 表选错。读的是只存在于输入寄存器里的量(功能码 03 与 04 混用)。
- 越界。从最后一个寄存器起读 10 个。
- 32 位当 1 个算。float32 占两个寄存器,只读一个只拿到一半,只写一个会把整对写坏。
- 设备映射有空洞。很多设备寄存器表并不连续,逐个读能定位断点。
4. Exception 03 — illegal data value异常码 03——非法数据值
The address was accepted, the value was not. Either the quantity is too large for one request, or the device rejects that particular value.
地址认了,值不认。要么一次要得太多,要么这个具体数值设备不接受。
- More than 125 registers or 2000 coils in one read.
- FC05 sent something other than
0xFF00or0x0000— the ON/OFF encoding is not "1" and "0". - Writing outside the allowed range: a setpoint of 200 °C on a heat pump that tops out at 60.
- Writing a register that is read-only in the current mode (e.g. while a schedule is active).
- 单次读超过 125 个寄存器或 2000 个线圈。
- FC05 发的不是
0xFF00或0x0000——开关量不是用 "1" 和 "0" 编码的。 - 写入超出允许范围:热泵上限 60 ℃,你写 200。
- 写了当前模式下只读的寄存器(例如定时任务运行时)。
5. It answers, but the numbers are nonsense能应答,但数值离谱
Nine out of ten times this is byte or word order. Put the registers into the converter and read across the row: one of the four columns will be the value you expect.
十次里有九次是字节序 / 字序问题。把寄存器粘进转换页横向对比,四列里总有一列是你期望的值。
- Shifted decimal point — the register is a scaled integer: 235 means 23.5. Look for a "÷10" note in the manual.
- Signed vs unsigned — 65526 is −10 as int16. Temperatures below zero show up as huge positive numbers.
- Two registers, one value — a float32 read as two uint16 looks like a pair of random large numbers.
- Stale value — the read succeeded but the device returns a cached value until its next control cycle; poll twice a second apart.
- 小数点位置不对——寄存器是缩放整数,235 表示 23.5。手册里通常有一句"除以 10"。
- 有符号 / 无符号——65526 按 int16 就是 −10。零下温度会显示成很大的正数。
- 两个寄存器一个值——float32 按两个 uint16 读,就是两个看不出规律的大数。
- 值不刷新——读成功了但设备返回的是缓存,直到下一个控制周期才更新;间隔一秒连读两次。
6. Works, then fails after a while一开始正常,跑一阵就出错
- Polling too fast. Give the device time to answer: at 9600 baud a full request/response already takes tens of milliseconds. Add 50–100 ms between polls.
- Inter-frame gap too short. Frames must be separated by 3.5 character times (3.65 ms at 9600). Many USB adapters buffer and coalesce writes, breaking this.
- Adapter latency timer. FTDI default latency is 16 ms — it delays every response. Lower it in device manager to 1–2 ms.
- Thermal drift in termination or bias resistors, or a connector that is barely making contact.
- Another master on the bus. Two pollers on the same RS-485 segment collide and both see corrupted frames.
- 轮询太快。要给设备留应答时间:9600 波特率下一次完整问答本身就要几十毫秒。两次轮询之间加 50–100 ms。
- 帧间隔太短。帧之间必须空 3.5 个字符时间(9600 下 3.65 ms)。很多 USB 转接器会把多次写合并,直接破坏这个间隔。
- 转接器延迟定时器。FTDI 默认延迟 16 ms,等于给每次应答加了 16 ms。设备管理器里改成 1–2 ms。
- 终端/偏置电阻温漂,或者接插件接触不良。
- 总线上有第二个主站。同一段 RS-485 上两个轮询方会互相撞帧,双方都看到坏帧。
7. Modbus TCP connects but goes nowhereModbus TCP 连上了但没数据
- Port 502 is the registered port but not mandatory — some devices use 503 or 1502. Check the manual.
- Unit ID still matters. Behind a gateway, the unit byte selects which serial device on the other side. Using 0 or 255 often works, often does not.
- MBAP length wrong — the length field counts the unit byte plus the PDU, not the whole frame. A client that gets this wrong is ignored silently.
- One connection at a time. Many small devices accept a single TCP client; a second connection blocks or drops the first.
- Firewall / VLAN — a TCP connect that succeeds but returns nothing can also be a proxy answering for a dead host.
- 端口 502 是注册端口但不是强制的,有的设备用 503 或 1502,看手册。
- 从站地址依然有效。经过网关时,从站字节决定后面串口上哪台设备。填 0 或 255 有时能用,有时不能用。
- MBAP 长度写错——长度字段算的是"从站地址 + PDU",不是整帧。客户端算错时服务器会静默丢弃。
- 只允许一个连接。很多小设备只支持单个 TCP 客户端,第二个连接会把第一个挤掉。
- 防火墙 / VLAN——TCP 能连上但没数据,也可能是代理替一台已经掉线的设备应答握手。
A five-minute diagnostic order五分钟排查顺序
| # | Check | If it fails |
|---|---|---|
| 1 | Loopback: short TX to RX on the adapter, send a frame, see it echo | Driver or adapter problem, not the device |
| 2 | Baud / parity / data / stop bits match the manual exactly | Fix and retry before touching wiring |
| 3 | Unit ID 1, function 03, start 0, quantity 1 | Nothing? Try 2, 3, 247; swap A/B |
| 4 | Raw bytes look like a valid frame; CRC passes | Electrical: termination, ground, cable length, baud |
| 5 | Exception code returned | Protocol-level: address map or value range |
| 6 | Values plausible in one byte order | Byte/word order or scaling factor |
Steps 3–6 need no hardware other than the adapter: build the frame in the frame builder, send it, and paste whatever comes back into the decoder.
第 3–6 步除了转接器不需要别的硬件:在帧构建页生成报文,发送,把回来的字节粘进解析器即可。