- 1. 异常帧长什么样
- 2. 0x01 — Illegale Funktionen码
- 3. MeldungBeispiel
- 4. 案例 1:台达 DVP 系列 PLC 不支持诊断Funktionscode
- 5. 案例 2:西门子 S7-1200 做 Modbus Server 时不支持读线圈
- 6. 案例 3:变频器Betrieb时禁止写Parameter
- 7. 案例 4:Modbus Plus 特有的Funktionscode在 TCP 网关上被拒
- 8. 0x02 — Illegale Datenadressen
- 9. MeldungBeispiel
- 10. 案例 1:Schneider TM3 扩展模块Adresse不够
- 11. 案例 2:Modbus Poll Adresse 40001 和 400001 的坑
- 12. 案例 3:读多ein Register.时末尾Adresse越界
- 13. 案例 4:离散输入和Schleife Adresse混淆
- 14. 0x03 — Illegale Datenwerte
- 15. MeldungBeispiel
- 16. 案例 1:写 EEPROM Parameter超出配置范围
- 17. 案例 2:对只读Register.执行写Operationen
- 18. 案例 3:多Register.写 —— 部UnterteilungFeld值非法
- 19. 案例 4:Modbus 电表的需Quantität复位Register.权限控制
- 20. 0x04 — Ausfall aus der Station
- 21. MeldungBeispiel
- 22. 案例 1:Modbus Der Sensor EEPROM 写入失败
- 23. 案例 2:温控器探头短路导致 AD 转换异常
- 24. 案例 3:扩展 I/O 模块掉线
- 25. 案例 4:模拟Quantität输入模块过压保护触发
- 26. 0x05 — Bestätigen(ACK)
- 27. MeldungBeispiel
- 28. 案例 1:变频器Parameter写入 EEPROM
- 29. 案例 2:TemperaturDer Controller PID 自整定
- 30. 案例 3:网关后端的Von der StationAntwort慢
- 31. 0x06 — Von der Station忙
- 32. MeldungBeispiel
- 33. 案例 1:写完Parameter立即读
- 34. 案例 2:高速轮询导致低速Ausrüstung缓冲区溢出
- 35. 案例 3:多Hauptstation同时访问一个Von der Station
- 36. 案例 4:Von der Station上电初始化期间收zuBitte
- 37. 0x0A — Gateway-Pfad nicht verfügbar
- 38. MeldungBeispiel
- 39. 案例 1:Seriöser Server后端的Von der Station掉线
- 40. 案例 2:网关配置了Fehler.的下游Parameter
- 41. 案例 3:Modbus TCP 级联网关
- 42. 厂商Custom definiertUngewöhnlicher Code
- 43. 用 Wireshark 抓异常帧
- 44. TCP Szene
- 45. RTU Szene
- 46. Modbus Poll 里的异常提示
- 47. Tests方法论:收zuUngewöhnlicher Code后的排查清单
- 48. Ungewöhnlicher Code速查表
异常帧长什么样
Modbus 的Ungewöhnliche Reaktion和正常Antwort只有一位之schlecht。Hauptstation发出Bitte后,Von der Station把Funktionscode的最高位置 1,后面跟一个单Bytes的Ungewöhnlicher Code,帧就Ende了。没有Datenzone。
正常帧 vs 异常帧的结构对比:
Bitte: 01 03 00 00 00 01 — 读 1 Nr.站,保持Register. 0x0000
正常Antwort: 01 03 02 12 34 — 02=DatenAnzahl der Bytes,0x1234=读回的值
Ungewöhnliche Reaktion: 01 83 02 — 83=0x03|0x80,02=Ungewöhnlicher Code 0x02
上面这个例子:Funktionscode 0x03 的最高位置 1 后变成 0x83。Ungewöhnlicher Code 0x02 代表「Illegale Datenadressen」——说明 0x0000 这个Adresse在该Von der Station里nicht existiert.。
多看一眼 CRC-Prüfung:不管正常Antwort还是Ungewöhnliche Reaktion,CRC 都是von der Station Adresse开始算zu最后一个DatenBytes(不含 CRC 自己)。上面我故意没写 CRC,实际帧末尾还有两个Bytes。
RTU 和 TCP 的异常帧有区别,schlecht异在封装层。TCP 的 MBAP 头里有一个 2 Bytes的「Länge」Feld,这个Länge包含了Einheitenidentifikator + Funktionscode + Ungewöhnlicher Code。而 RTU 靠 3.5 Charaktere静默Zeit来Unterteilung隔帧。Vereinbarung层不一样,但Funktionscode和Ungewöhnlicher Code的语义完全一样——这是 Modbus 最干净的设计之一。
还有一个细节容易被忽略:Ungewöhnliche Reaktion的帧Länge是固定的。对Funktionscode 0x01~0x06,Ungewöhnliche Reaktion永远只有 3 个Bytes(Adresse + Funktionscode|0x80 + Ungewöhnlicher Code),CRC 另算。对 0x0F 和 0x10 这类多OperationenFunktionscode,Ungewöhnliche Reaktion也是 3 Bytes。Von der Station不需要告诉你「哪一部Unterteilung出错了」,只告诉你「整个Bitte被拒了」。这个设计很粗暴,但也很简单——Hauptstation收zuUngewöhnlicher Code后自己想办法重试或报错。
Die Serie层面的时序也有讲究。Modbus RTU 规定Von der Station必须在收zuBitte后的指定Zeit内开始Antwort——但标准并没有硬性规定这个Zeit的具体值。实践中多数Von der Station的AntwortZeit在 5~50ms 之间。超过 1 秒没收zuAntwort(或者没收zu异常帧),Hauptstation应该认为Von der Station无Antwort——这是超时,不是Ungewöhnlicher Code。很多Arbeitskontrolle软件把「No Response」和「Exception Response」混在一起报,给你一种Geräte zurück.了Ungewöhnlicher Code的错觉。实际上Von der Station根本没回任何东西。区Unterteilung这两种情况对排查问题至关重要——没Antwort是链路层或Ausrüstung层的问题,Ungewöhnlicher Code是Von der Station应用层在告诉你「我收zu了但我不干」。
下面逐个拆解 7 种标准Ungewöhnlicher Code。每个都配了真实Meldung和现场案例——不是拿 Wireshark 仿真抓的,是产线、变电站、水泵房里实实在在遇zu的。
0x01 — Illegale Funktionen码
Von der Station不支持HauptstationBitte的Funktionscode,或者Von der StationgegenwärtigStatus下该Funktionscode被禁用了。
你给一台支持 03/06/16 的标准 Modbus Ausrüstung发 0x08 诊断Funktionscode,大概率收zu 0x01。因为诊断Funktionscode是可选的,很多廉价 I/O 模块根本没实现。
MeldungBeispiel
Bitte: 02 08 00 00 AA 55
Ungewöhnliche Reaktion: 02 88 01
0x08 = 诊断,子码 0x0000 = 回环测试,Daten 0xAA55。Von der Station直接回 0x88(0x08|0x80) + 0x01。
案例 1:台达 DVP 系列 PLC 不支持诊断Funktionscode
台达 DVP-SX2 系列,固件版本 V3.8。项目中做 RS-485 线路质Quantität测试,用 Modbus Poll 的 Test Center 发 0x08 诊断,Ergebnis返回Ungewöhnlicher Code 0x01。翻了 DVP 的手册Bestätigen:DVP 只实现了 01/03/05/06/0F/10 六个Funktionscode,0x08 不在其列。想要诊断线路质Quantität只能用 0x01 Lesen Sie die Schleife或者 0x03 读Register.,通过AntwortZeit和连续成功率间接判断。这个事情告诉我们,诊断Funktionscode虽然写进了 Modbus 标准,但不是所有厂商都买账。
案例 2:西门子 S7-1200 做 Modbus Server 时不支持读线圈
西门子 S7-1200 从 TIA Portal V14 开始支持 Modbus TCP Server。但它的实现只是把 DB 块映射zu保持Register.(0x03/0x06/0x10),线圈 0x01/0x05/0x0F 压根没做。跟上位机Tests的时候,SCADA 用 0x01 去读AusrüstungStatus字,S7-1200 直接甩回一个 0x81 + 0x01。解决办法:把Schleife Adresse映射zu保持Register.区段,上位机改用 0x03 读。
案例 3:变频器Betrieb时禁止写Parameter
汇川 MD500 变频器,BetriebStatus下尝试用 0x06 写频率给定Register. 0x2000。返回 0x01。不是变频器不支持 0x06 Funktionscode,而是gegenwärtigStatus不允许写。汇川的手册里管这叫「Betrieb禁止写入」,但Vereinbarung层用的就是标准Ungewöhnlicher Code 0x01。这种语义扩展在很多国产Ausrüstung上都能见zu——用标准Ungewöhnlicher Code表达厂商Custom definiert的限制条件。
案例 4:Modbus Plus 特有的Funktionscode在 TCP 网关上被拒
一台老旧的 Modicon Quantum PLC,通过 BM85 网桥做 Modbus Plus zu Modbus TCP 的转换。Modbus Plus 有自己的一套扩展Funktionscode(0x14~0x18 用于网络管理),但 BM85 网桥只透传标准 Modbus Funktionscode。上位机不小心发了 0x14 读 PLC 统计信息的Bitte,网桥在应用层检查后直接返回 0x81+0x01。注意这里返回Ungewöhnlicher Code的是网关,不是 PLC——PLC 可能支持 0x14,但网关不支持。网桥日志里没有这个Funktionscode的Analyse路由,直接拒绝了。网关做Funktionscode安全过滤的情况在实际项目里很Häufig,尤其是有防火墙Funktion的工业路由器。
0x02 — Illegale Datenadressen
Von der Station支持该Funktionscode,但Bitte的Ausgang Adresse + Anzahl超出了Von der Station的WirksamAdresse范围。这是现场Tests碰zu最多的Ungewöhnlicher Code,没有之一。
关键点:Hauptstation软件里填的Adresse和Vereinbarung层实际Senden Sie的Adresse有 offset。Das Modbus-Protokoll规定,Adresse从 0 开始编Nr.。你在 Modbus Poll 里填的 40001(1-based 保持Register.),Vereinbarung层发的是 0x0000。AdresseBerechnung逻辑弄反了,轻则读zuFehler.Daten,重则触发 0x02。
PLC/SCADA Adresse表示: 40001 (1-based, 保持Register.)
Vereinbarung层 PDU Adresse: 0x0000 (0-based)
MeldungBeispiel
Bitte: 01 03 00 64 00 0A — 读 0x0064 = 400101,读 10 个
Ungewöhnliche Reaktion: 01 83 02
Von der Station的Wirksam保持Register.范围是 40001~40090(即 PDU Adresse 0x0000~0x0059),Bitte的Ausgang Adresse 0x0064 超了,直接 0x02。
案例 1:Schneider TM3 扩展模块Adresse不够
Schneider Modicon M221 挂了两块 TM3 扩展。配置里Die一块 TM3DI16 占 %IW0~%IW1,Die二块 TM3AI4 占 %IW2~%IW5。上位机 SCADA 用 0x04(Eingangsregister lesen)去读 %IW10,Von der Station返回 0x02。原因很简单——M221 只Unterteilung配了 %IW0~%IW5,%IW10 不在物理 I/O 映射里。SoMachine 里看一眼 I/O 映射表就明白了。这种问题属于配置和实际硬件不匹配,不是Vereinbarung缺陷。
案例 2:Modbus Poll Adresse 40001 和 400001 的坑
一个新手工程师用 Modbus Poll 点表里抄的Adresse是 40001,Modbus Poll 实际发的是 0x0000,读zu的是AusrüstungDie一个保持Register.,没问题。但后来换了另一个国产Strukturen软件,那个软件把 40001 Analyse成了 4000 + 1 的偏移Quantität,实际发的是 0x0FA0。Von der Station根本没有那么多Register.,返回 0x02。同一份点表、同一个Von der Station,不同的Hauptstation软件Adresse约定不一样,Ergebnis就不一样。这不是 Das Modbus-Protokoll的问题,是Werkzeuge链各玩各的约定导致的。建议直接用 PDU Adresse(0-based)跟同事沟通,别说什么 4 区 5 区,那都是 Modicon 的老黄历。
案例 3:读多ein Register.时末尾Adresse越界
一台 Modbus 电表,保持Register. 0x0000~0x003F(64 ein Register.)。HauptstationBitte读 0x0038 起 10 ein Register.(0x0038~0x0041)。Von der Station检查:最后一个Adresse 0x0038 + 9 = 0x0041 > 0x003F,直接扔 0x02。很多Von der Station在做Adresse合法性检查时,会先算Anfang + Anzahl是否在范围内,只要任何一个Adresse越界就整包拒绝。不是一ein Register.越界返回部UnterteilungDaten——Modbus 标准没有部UnterteilungAntwort的概念。
案例 4:离散输入和Schleife Adresse混淆
这个坑在用了 Modicon 老式 5 位Adresse标注的Unternehmen里特别Häufig。1xxxx 是离散输入(只读位),0xxxx 是线圈(读写位)。上位机Strukturen里配置了Adresse 10001 来读AusrüstungStatus,但实际该Von der Station把AusrüstungStatus放在了线圈区(0xxxx 对应 0x01 Funktionscode)。上位机用 0x02(Lesen Sie getrennte Eingabe)去BitteAdresse 0x0000,Von der Station里 0x0000 在离散输入区确实nicht existiert.——离散输入总共有 8 路(Adresse 0x0000~0x0007)但那 8 路已经Unterteilung配给了其他 DI。Von der Station返回 0x02。换个Funktionscode或者换个Adresse都能解决,但前提是你得知道Von der Station的Adresse映射表长什么样。不少Arbeitskontrolle工程师直接把所有离散信Nr.全映射zu线圈区或全映射zu保持Register.里,省得用户搞混——但前提是你手里的Von der Station允许你这么做。
0x03 — Illegale Datenwerte
AdresseWirksam、FunktionscodeWirksam,但Bitte体中携带的Daten值不在允许范围内。
这是一个容易被忽略的Ungewöhnlicher Code。很多时候你会先怀疑Adresse配置错了,但实际是写的值越界了。
MeldungBeispiel
Bitte: 01 06 00 10 FF FF — Schreiben eines einzelnen Registers,Adresse 0x0010,值 0xFFFF
Ungewöhnliche Reaktion: 01 86 03 — Funktionscode 0x06|0x80 = 0x86,Ungewöhnlicher Code 0x03
为什么 0xFFFF(65535)非法?因为那ein Register.是 0~10000 的工程值范围。65535 在 16 位表示上是合法的,但在业务逻辑上不合法。
案例 1:写 EEPROM Parameter超出配置范围
欧姆龙 E5CC 温控器,Register. 0x0103(PID 比例带)。该Parameter的Wirksam范围是 0.1~999.9,以 0.1°C 为单位存储,即Registerwert 1~9999。上位机下发 0x0000(即 0.0°C),Von der StationPrüfungen后发现值kleiner als下限 1,返回 0x03。手册上写了范围,但上位机代码里偷懒没做边界检查。调了半小时才发现是写值超范围——这种低级Fehler.每个人都会犯,重要的是记住先翻手册再看Ungewöhnlicher Code。
案例 2:对只读Register.执行写Operationen
ABB ACS580 变频器,Register. 0x2104(实际转速反馈,只读)。上位机试图用 0x06 写入 1500(想手动给转速值),Von der Station返回 0x03。0x2104 这个Adresse本身Existenz,Funktionscode 0x06 也被支持,但该Adresse在Von der Station内部被标记为只读属性。「Illegale Datenwerte」在这里的含义是「你往一个不接受写入的Adresse写了Daten」——不是值本身非法,是写这个动作非法。Modbus-Protokollspezifikation里,0x03 的措辞是「Value is not allowed」,给了Von der Station实现自由度。许多厂商就把只读保护归zu 0x03 下。
案例 3:多Register.写 —— 部UnterteilungFeld值非法
用 0x10 批Quantität写 5 ein Register.,前 4 个值没毛病,Die 5 ein Register.要求值在 0~100,你写了 200。有些Von der Station会PrüfungenAllesDaten后才回复,5 个全合法就执行,任何一个不合法就整体拒绝返回 0x03。有些Von der Station则逐个Prüfungen、发现Die一个不合法就拒绝。规范没说必须按哪种方式,各家的实现不一样。建议你对自己用Die Ausrüstung做一下边界测试,心里有数。
案例 4:Modbus 电表的需Quantität复位Register.权限控制
施耐德 PM800 系列电力仪表,Register. 0x2F01(需Quantität复位Befehl)只能写入特定的控制字组合(0x1234 或 0x5678)。上位机误写了 0x0001 试图清需Quantität,仪表返回 0x03。手册上明确写了:复位BefehlRegister.的Wirksam值是 0x1234 和 0x5678,其他任何值都触发 0x03。这个设计是为了防止误Operationen——毕竟某些Register.写错了不是报错那么简单,是真的会改Parameter。
还有一个与 0x03 Related的陷阱:Funktionscode 0x06 Schreiben eines einzelnen Registers时,如果该Register.是 32 位值的低 16 位,只写低 16 位而高 16 位未初始化,Von der Station可能返回 0x03。比如 AB ACS580 的Parameter 0x1000(32 位浮点),你必须用 0x10 一次写 2 ein Register.,不能拆成两个 0x06。Unterteilung开写的话Von der Station会在Die一个 0x06 时就报 0x03——因为它知道这个Adresse是 32 位对齐的,不接受 16 位写Operationen。
0x04 — Ausfall aus der Station
Von der Station在处理Bitte的过程中发生了不可恢复的内部Fehler.,导致Befehl无法执行。这个Ungewöhnlicher Code告诉你「不是你的Bitte有问题,是我自己坏了」。
0x04 是现场最让人紧张的Ungewöhnlicher Code。0x01~0x03 你改改配置就能解决,0x04 意味着可能要去车间里爬梯子了。
MeldungBeispiel
Bitte: 03 03 00 20 00 04 — 读 4 个保持Register.
Ungewöhnliche Reaktion: 03 83 04
同一个Bitte,十Unterteilung钟前还正常返回Daten,现在开始持续返回 0x04。硬件故障的可能性大了。
案例 1:Modbus Der Sensor EEPROM 写入失败
一台昆仑海岸 JWSK-6 Temperatur Feuchtigkeit变送器,Modbus RTU Schnittstelle。Fern entfernt改了Geräte Adresse从 0x01 zu 0x05,写 EEPROM 的过程中供电抖动了一下。写入失败,Ausrüstung固件检测zu EEPROM checksum 不匹配,进入了 fail-safe 模式。之后所有FunktionscodeBitte(不管 0x03 读还是 0x06 写)Alles返回 0x04。查了手册Bestätigen:该Der Sensor在 EEPROM 自检失败后会锁死Kommunikation,只能物理断电重启恢复出厂设置。这属于固件保护机制——比让你读zuFehler.值强。
案例 2:温控器探头短路导致 AD 转换异常
RKC CB100 温控器,热电偶输入端因为接线端子进水短路了。AD 转换芯片读zu的是溢出值,固件判定Der Sensor故障,然后所有 0x03 读 PV 值的Bitte都返回 0x04。这个 0x04 不是 Modbus Kommunikation芯片坏,是Der Sensor前端故障通过固件的异常传递机制反映zu了Vereinbarung层。换了个热电偶、擦干端子,0x04 消失了。
案例 3:扩展 I/O 模块掉线
Siemens ET200SP 通过Schnittstelle模块做 Modbus TCP Server。一个 DI 模块因为背板Verbindung器接触不良掉线了。对于掉线模块的Register-Adresse,Von der Station统一返回 0x04。但其他正常模块的Register-AdresseLesen正常。这说明Von der Station内部的故障隔离做得好——坏一块不影响全局。
案例 4:模拟Quantität输入模块过压保护触发
研华 ADAM-4117 模拟Quantität输入模块,Quantität程设置 0~5V。某个通道意外接入了 12V 信Nr.,模块内过压保护电路启动,该通道进入故障Status。所有 0x04 读该通道值的Bitte返回 0x04,配置文件显示Fehler.标志位置位。拔掉过压信Nr.、重新上电后恢复。这个 0x04 的根因在物理接线,不在KommunikationVereinbarung。排查时先把线甩了,再用仿真信Nr.测——不过我记得 ADAM-4117 有时要软复位,单靠重新上电不够。
0x05 — Bestätigen(ACK)
0x05 不是Fehler.。它是Von der Station对Hauptstation说:「收zu了,正在做,你先别催。」
标准措辞是「Acknowledge」。Von der Station已经接受了Bitte,但处理需要较长Zeit(比如写 Flash、执行自整定),先回一个 0x05 让Hauptstation知道Verbindung没断,后续处理abgeschlossen.后再通过正常Antwort或Status位告知Ergebnis。
这是 7 个标准Ungewöhnlicher Code里最特殊的一个——它是唯一不表示问题的Ungewöhnlicher Code。
MeldungBeispiel
Bitte: 01 06 0F A0 00 00 — 写Register. 0x0FA0 = 0x0000,触发Parameter保存
Ungewöhnliche Reaktion: 01 86 05
案例 1:变频器Parameter写入 EEPROM
台达 VFD-M 变频器,写 0x2000(BefehlRegister.)= 0x0010 触发「Parameter写入 EEPROM」Operationen。EEPROM 擦写周期在 10~30ms 左右。Von der Station收zuBefehl后先回 0x86 + 0x05,表示「知道你要保存Parameter,正在写 Flash」。大约 20ms 后可以再次轮询BefehlRegister.,读zu 0x0000 表示写入abgeschlossen.。如果在 0x05 之后 50ms 内没有abgeschlossen.,有些变频器会超时回退。
案例 2:TemperaturDer Controller PID 自整定
欧姆龙 E5CC,写 0x0101(AT 执行/Stopp!)= 0x0001 启动自整定。这个Operationen需要几Unterteilung钟。E5CC 先回 0x05,然后自整定过程中可以正常Lesen PV 和 SV 值,只是 AT 标志位为 ON。自整定abgeschlossen.后,AT 自动 OFF。上位机需要在收zu 0x05 后启动超时计时器,不要一直在那死等——有些Ausrüstung的自整定能跑 30 Unterteilung钟。
案例 3:网关后端的Von der StationAntwort慢
Modbus TCP 转 RTU 网关(比如 MOXA MGate MB3170),Hauptstation通过网关读一个 9600bps 低速总线上的Von der Station。Hauptstation发了读 125 ein Register.的Bitte,网关把这个Bitte转发zu RTU 总线,但因为DatenQuantität大、Porter Rate低,RTU Von der Station需要 200ms+ 才能回完Daten。网关在收zuvollständig RTU Antwort之前,先给 TCP Hauptstation回一个 0x05 占位——这就是网关Häufig的「pending」处理方式。Modbus TCP 规范里其实没有明确规定 0x05 在这种Szene下的用法,但很多网关厂商就这么干了。
一个需要注意的设计细节:0x05 触发后,Hauptstation侧的等待策略。不应立即重发同样的Bitte——这会让Von der Station收zu重复Befehl。Richtig.的做法是:轮询一个StatusRegister.(如果Von der Station提供了)或者设立超时计时器,超时后发新的查询Befehl。有些 SCADA 驱动(比如 Kepware 的 Modbus 驱动)内置了 0x05 的处理逻辑,有些则直接报超时。如果你自己写 Modbus 驱动,0x05 的处理逻辑是必做项。
0x06 — Von der Station忙
Von der Station现在太忙了,处理不了你的Bitte。Befehl被接受了但无法执行,Hauptstation应该稍后重试。
0x05 和 0x06 的区别:0x05 是「收zu了,在处理,等Ergebnis」;0x06 是「现在没空,你过会儿再来」。0x05 意味着Von der Station已经开始执行Befehl了,0x06 意味着Von der Station根本没开始执行。
MeldungBeispiel
Bitte: 01 06 20 00 07 D0 — 写Register. 0x2000 = 0x07D0(2000)
Ungewöhnliche Reaktion: 01 86 06 — 忙,没空处理
案例 1:写完Parameter立即读
写入一个需要写 EEPROM 的Parameter后,10ms 内立即发下一个Bitte。Von der Station Flash Der Controller还没释放总线,直接回 0x06。很多工程师在TestsDrehbuch里几毫秒一个Bitte连续发,Von der Station根本来不及处理。不是Ausrüstung慢,是你太快了。Modbus 没有流控机制,Hauptstation需要自己控制节奏——写完 Flash RelatedRegister.后,留 30~50ms 再发下一个读写Bitte。
案例 2:高速轮询导致低速Ausrüstung缓冲区溢出
用 Modbus Poll 以 20ms 间隔轮询一台 9600bps 的 RTU Temperatur FeuchtigkeitDer Sensor。刚启动时正常,Betrieb一Unterteilung钟后开始间歇性出现 0x06。9600bps 传输一个Bytes约 1ms,一个最小读Bitte+Antwort来回大概 30~40ms。20ms 的轮询间隔已经kleiner alsAusrüstung的最小Antwort周期。Von der StationDie SerieEmpfang缓冲区被塞满了,它在忙着丢弃溢出的帧,没精力处理新Bitte。把轮询间隔调zu 100ms 就好了。换成 115200bps 能进一步缩短,但很多ArbeitskontrolleAusrüstung最高只支持zu 38400bps 甚至 19200bps。
案例 3:多Hauptstation同时访问一个Von der Station
一个 RS-485 总线上的 Modbus RTU Von der Station,同时接了 PLC 和上位机 SCADA 两个Hauptstation。两个Hauptstation之间没有协调,各自以 500ms 和 300ms 间隔轮询。碰撞概率上来了——两个Bitte帧重叠,Von der Station收zu的是乱码。有些Von der Station在检测zu帧Fehler.后会忽略,有些Von der Station会消耗Zeit做Fehler.处理,导致刚LeerenEmpfang缓冲区时下一个Hauptstation的帧就zu了。还没准备好Empfang新帧,只能回 0x06。RS-485 多Hauptstation的冲突处理,建议上硬件流控或在Hauptstation侧做互斥锁,别指望Von der Station自己Erledigt.
案例 4:Von der Station上电初始化期间收zuBitte
大部Unterteilung Modbus Von der Station上电后有几十毫秒zu几秒的初始化Zeit。在这个窗口里发Bitte,Von der Station的 Das Modbus-Protokoll栈还没准备好。有些Von der Station直接不回(No Response),有些Von der Station回 0x06。这个行为跟具体的固件实现有关。丹佛斯 VLT FC302 变频器上电后大约 2 秒内会返回 0x06,初始化abgeschlossen.后恢复正常。如果你的 SCADA 启机就去读Von der Station,头几个Bitte可能收zu 0x06——在上位机代码里加个上电延迟或者对 0x06 做自动重试(间隔 500ms,最多 3 次)就能规避。
0x06 和 0x05 很容易搞混,这里说清楚:0x05 是「正在处理你的Bitte」,处理完了会回正常Daten。0x06 是「没空处理你的Bitte,Bitte被丢弃了」。Hauptstation收zu 0x05 应该等待,收zu 0x06 应该重试。如果把 0x06 当成 0x05 处理——等着等着就超时了。
0x0A — Gateway-Pfad nicht verfügbar
这个Ungewöhnlicher Code只在网关Szene出现。网关和下游Von der Station之间的Kommunikation出了问题——网关本身没问题,但它后面Die Ausrüstung连不上了。
Modbus 标准定义的措辞是「Gateway Path Unavailable」——无法建立zu目标Ausrüstung的路径。这里的目标Ausrüstung不是Adresse 0x01 的Von der Station本体,而是网关内部的「路由」zu下游Von der Station的路径。
MeldungBeispiel
Bitte: 01 03 00 00 00 01 — 通过网关读下游Von der Station
Ungewöhnliche Reaktion: 01 83 0A — 网关:后面那个Von der Station没Antwort
案例 1:Seriöser Server后端的Von der Station掉线
USR-N510 Seriöser Server做 Modbus TCP 转 RTU 网关,下面挂了 3 台 Modbus RTU Der Sensor(Adresse 0x01、0x02、0x03)。0x02 Von der Station因为电源模块烧了,完全掉线。Hauptstation通过网关读 0x02 Von der Station时,Seriöser Server尝试在 RS-485 总线上RundfunkBitte,等 500ms 超时没收zuAntwort,然后在 TCP 侧给Hauptstation回了 0x0A。0x01 和 0x03 Von der Station的Kommunikation完全正常——网关本身活着,只是某一条路径断了。
案例 2:网关配置了Fehler.的下游Parameter
MOXA MGate MB3170,配置下游为 9600bps、8N1。但实际 RS-485 总线上Die Ausrüstung是 19200bps、8E1(Zufällige Prüfungen)。网关按照 9600bps 发Bitte帧,Von der Station收zu的是乱码,不Antwort。网关超时后返回 0x0A。这种问题在有多家Die Ausrüstung混装的 RS-485 总线上尤其Häufig——不同厂商的默认Kommunikationsparameter不一样,项目初期不统一调一遍就会踩坑。
案例 3:Modbus TCP 级联网关
一个大型VerteilungSzene:中心 SCADA → Modbus TCP 主网关 → 光纤环网 → 就地子网关 → RS-485 Von der Station。主网关zu子网关之间的光纤断了,主网关对子网关下面所有Von der Station的Bitte都返回 0x0A。这时候排查思路是逐级 ping:先Bestätigen主网关zu子网关的 TCP Verbindung,再Bestätigen子网关zu RS-485 总线,最后才是Serielle Ausrüstung本身。
厂商Custom definiertUngewöhnlicher Code
除 7 种标准Ungewöhnlicher Code,很多厂商在 0x80~0xFF 区段定义了私有Ungewöhnlicher Code。这不是违反标准——Modbus 规范允许厂商扩展。但你的上位机代码如果只认识 01~0A,碰zu 0x90 就会报「Unknown Exception」或者直接丢帧。
一些Häufig厂商扩展:
| 厂商 | Custom definiertUngewöhnlicher Code | 含义 |
|---|---|---|
| 西门子 S7-1200/1500 | 0x80 | Modbus Server DB 块未初始化 |
| 汇川 AM600 | 0x81 | Parameter锁定(需要先写解锁Register.) |
| 台达 AS 系列 | 0x8B | Funktionscode在gegenwärtig PLC Betrieb模式下被禁止 |
| 部Unterteilung国产温控器 | 0x90~0x9F | ParameterPrüfungen失败(写值与 EEPROM 不符) |
| Schneider M221 | 0xF0 | 固件不支持的Register.区域 |
这些Ungewöhnlicher Code没有统一标准,得翻各家手册。有些厂商在手冊的 Modbus KommunikationKapitel节会列出vollständig的Ungewöhnlicher Code表,有些藏在附录里,还有些干脆不写——你只能 debug 抓zu之后凭经验判断。
有个坑:部Unterteilung国产 PLC 在遇zu 0x02 条件时也会回 0x03(不区Unterteilung非法Adresse和Illegale Datenwerte),因为它们内部的异常处理把「Adressenicht existiert.」和「值不合法」归为同一个Fehler.路由。你按标准预期是 0x02,实际收zu 0x03——别较真,对着手册的Registerabbildung表查就是了。
还有一个容易被忽略的:CPU 停机模式下的Ungewöhnlicher Code行为。很多 PLC 在 STOP Status下仍然Betrieb Das Modbus-Protokoll栈,但行为不同。西门子 S7-1200 做 Modbus Server 时,CPU 从 RUN Wechselnzu STOP,读zu已映射的 DB 块返回 0x04(「Ausrüstung故障」),而不是 0x01。这个语义很微妙——PLC 没坏,但在 STOP 模式下 DB Daten不可用。施耐德 M221 在 STOP Status下则仍然Antwort Modbus Bitte,只是Daten不更新。三菱 FX5U 做 Modbus Server 时,STOP Status下直接不Antwort任何Bitte,上位机看zu的是超时,不是Ungewöhnlicher Code。同一套 SCADA Das System要适配不同品牌 PLC 的 STOP 行为,驱动层面就得做schlecht异化处理。
厂商扩展Ungewöhnlicher Code还经常被用于安全Szene。比如某些支持 Modbus Security(基于 TLS)的网关Ausrüstung,会在认证失败时返回Custom definiertUngewöhnlicher Code 0xE0~0xEF 表示安全层拒绝。这不是 Modbus 标准定义的,但确实Existenz。如果你的 Modbus TCP Kommunikation突然开始收zu 0xE1,不是Vereinbarung栈Analyse错了,是网关在告诉你「TLS 握手没过」。
用 Wireshark 抓异常帧
不管 RTU 还是 TCP,Wireshark 都能直接Analyse Das Modbus-Protokoll。前提是你的抓包点在Richtig.的网络位置。
TCP Szene
Modbus TCP 走 502 端口,Wireshark 默认就Analyse。在过滤器栏输入 `modbus`,异常帧会显示为红色背景。
展开Ungewöhnliche Reaktion帧,看这几个关键Feld:
Modbus/TCP
Transaction Identifier: 1
Protocol Identifier: 0
Length: 3 ← 注意这个Länge
Unit Identifier: 1
Modbus
Function Code: 131 (0x83) ← 83 = 03 | 0x80,Wireshark 直接显示了
Exception Code: 2 (Illegal Data Address)
`Length: 3` 是 MBAP 头里的LängeFeld,它 = Unit Identifier(1) + Function Code(1) + Exception Code(1) = 3 Bytes。正常Antwort这个值会更大(因为后面有Daten)。只看Länge就能初步判断是Ungewöhnliche Reaktion还是正常Antwort——Ungewöhnliche Reaktion的 TCP 载荷通常只有 3 Bytes。
RTU Szene
RTU 抓包需要用 RS-485 转 USB Konverter.搭一个监听节点。Wireshark 对 RTU 的支持不如 TCP 好,需要手动指定端口配置(Porter Rate、Prüfungen等)。抓zu的异常帧Das Format和 TCP 类似,但没有 MBAP 头:
01 83 02 xx xx — Adresse 01,Funktionscode 83,Ungewöhnlicher Code 02,CRC xx xx
RTU 抓包里没有 Transaction ID,你只能靠Zeit戳来判断Bitte和Antwort的对应关系。Tests复杂的多Von der Station RTU 总线时,建议在 Wireshark 里按 Modbus Adresse过滤,把每个Von der Station的流QuantitätUnterteilung开看。
Wireshark 的 Modbus Analyse器从 3.x 版本开始支持Ungewöhnlicher Code的中文显示。在 Preferences → Protocols → Modbus 里勾选 Exception 的Analyse选项。但注意:Wireshark 只能Analyse标准Ungewöhnlicher Code 01~0A,厂商Custom definiert码会显示数字而非描述Text。
还有一个 Wireshark 小技巧:用 `modbus.exception_code` 做显示过滤器。`modbus.exception_code == 2` 过滤出所有 0x02 异常帧。`modbus.exception_code >= 1 && modbus.exception_code <= 10` 过滤所有标准异常。在现场排查时,先看全局统计——Statistics → Protocol Hierarchy → Modbus,能看zu异常帧占Kommunikation总Quantität的百Unterteilung比。如果异常帧超过 10%,你的配置大概率有问题。如果只有偶发的 0x06,那是时序问题。如果持续 0x04,准备换Ausrüstung。
Modbus Poll 里的异常提示
Modbus Poll 是am häufigsten verwendet的Debugging-Tools。它的异常信息直接显示在窗口底部Status栏,长这样:
Modbus Exception Response
Function: 3, Exception: 2 (Illegal Data Address)
Die一眼看zu红字别慌,先看 Function Was ist das?,再看 Exception Was ist das?。Funktionscode告诉你哪个Operationen报错了,Ungewöhnlicher Code告诉你为什么。
Öffnen. Display → Communication,能看zuvollständig的Nachrichten empfangen。异常帧用红色标记,点开看原始16. System:
Tx: 01 03 00 00 00 01 84 0A
Rx: 01 83 02 C0 F1
`Rx` 的Die二Bytes是 0x83(=0x03|0x80),Die三Bytes 0x02 就是Ungewöhnlicher Code。`C0 F1` 是 CRC。Modbus Poll 帮你Analyse出来了,但学会自己看原始帧是一项基本功——上线部署后你不会永远有 Modbus Poll 可以用。
同一个Bitte连续报 0x02,先别改Adresse,先Bestätigen你的Ausgang Adresse和Anzahl是否在Von der Station手册列出的Wirksam范围内。很多时候是AdresseBerechnung逻辑错了,不是你Adresse写错了。尤其是从 1-based Register-AdresseWechselnzu 0-based PDU Adresse的时候——这个坑基本每个新手都要踩一次。
Tests方法论:收zuUngewöhnlicher Code后的排查清单
现场出了Ungewöhnlicher Code,按下面这个顺序走——不是标准Operationen流程,是老工程师的血泪经验。
**Die一步:Bestätigen是哪个Von der Station、哪个Funktionscode、哪个Ungewöhnlicher Code**
因为现场通常不止一台Von der Station。用 Modbus Poll 或 Wireshark 抓Original-Meldung,拿zuvon der Station Adresse + Funktionscode + Ungewöhnlicher Code这三个数。如果你是用Drehbuch在测,加一行 `print(hex(response[0]), hex(response[1]), hex(response[2]))`,别只看日志里的「Kommunikation失败」。
**Die二步:Ungewöhnlicher CodeKlassifizierung——软件原因还是硬件原因?**
0x01 / 0x02 / 0x03 大概率是你的Bitte有问题。查配置、查Adresse映射、查Daten范围。0x04 / 0x0A 大概率是Von der Station或链路有问题。先断电重启Von der Station试试——如果是 0x04 变正常了,说明是Ausrüstung内部故障恢复,但不代表根本原因已解决。0x06 是时序问题,调慢轮询间隔。
**Die三步:隔离变Quantität**
同一台Hauptstation,换一个von der Station Adresse试试。能Kommunikation → 问题在原Von der Station。不能Kommunikation → 问题在Hauptstation端或总线。同一个von der Station Adresse,用 Modbus Poll 试试。能Kommunikation → 你的上位机代码有问题。不能Kommunikation → Von der Station或链路有问题。这是最Häufig的二Unterteilung排查法,但很多人跳过了这一步,直接怀疑硬件坏了。
**Die四步:看手册**
Ungewöhnlicher Code出来了,翻Von der Station手册的 Modbus KommunikationKapitel节。有些厂商会列出所有可能返回的Ungewöhnlicher Code和触发条件。如果手册没有Ungewöhnlicher Code表,找Adresse映射表,手动对照你的BitteAdresse是否在Wirksam范围内。很多现场的「Kommunikation故障」其实是你读了一个保留Adresse或者只写Adresse。
**Die五步:抓包**
用 Wireshark 或者Die Serie监控Werkzeuge抓Original-Meldung。看的是:Hauptstationzu底发出了什么?Von der Stationzu底回复了什么?有没有 CRC Fehler.?有没有帧不vollständig?很多时候你看日志以为发出去了 01 03 00 00 00 01,实际抓包发现Porter Rate错了Von der Station当噪音扔了。不要相信你的代码日志,要相信抓包Werkzeuge。
**Die六步:替换测试**
换一台同型Nr.的新Von der Station接上去,同样的Bitte看Ergebnis。如果新Ausrüstung正常,原Ausrüstung返Ungewöhnlicher Code——Ausrüstung硬件故障。如果新Ausrüstung也返同样的Ungewöhnlicher Code——你的Bitte有问题。如果手头没有备用Ausrüstung,换一个确定能正常工作的von der Station Adresse来测Kommunikation链路。链路的嫌疑排除了,问题就在特定Ausrüstung上。
**Die七步:如果还是搞不定**
把Original-Meldung(16. System)、Von der Station型Nr.和固件版本、你的Hauptstation平台信息发给Von der Station厂商的 FAE。别发日志截图,发Original-Meldung——FAE 看Original-Meldung比看你的描述准得多。如果 FAE 也不回,去 modbus.cn 论坛贴Original-Meldung求助。社区的Tests经验有时比厂商手册还靠谱,因为手册是理论,社区是血泪。
**补充:自己写 Modbus 驱动时的Ungewöhnlicher Code处理模板**
如果你在写上位机的 Modbus Hauptstation驱动(用 C/Python/Node.js 等),异常帧处理至少要覆盖这几种情况:
1. 检查Antwort的Die一个Bytes是否gleich istBitte的von der Station Adresse(Adresse不Übereinstimmung = 不是给你的Antwort,丢弃) 2. Funktionscode的 bit 7 是否为 1(为 1 则提取Ungewöhnlicher Code,为 0 则正常AnalyseDatenzone) 3. Ungewöhnlicher Code 0x05 特殊处理:不抛出异常,进入等待Status,轮询StatusRegister.或超时重发 4. Ungewöhnlicher Code 0x06 特殊处理:延迟 50~100ms 后重试,最多重试 3 次 5. 其他Ungewöhnlicher Code:记录日志、通知上位层进行Fehler.处理(告警、重试、Wechseln备用链路等) 6. 厂商Custom definiert码 0x80~0xFF:需要Ausrüstung型Nr.Related的字典来Analyse,否则按 Unknown Exception 处理
Fehler.的做法是把所有Ungewöhnlicher Code都当作「Kommunikation失败」然后重试——0x02 重试一万次也是 0x02,Adresse错了就是错了。Richtig.的做法是根据Ungewöhnlicher CodeKlassifizierung采取不同策略。这部Unterteilung逻辑写好了,你的驱动就能适配市面 90% 的 Modbus Von der StationAusrüstung。剩下的 10% 是那些不按标准返回Ungewöhnlicher Code的厂商——它们用正常Antwort替代Ungewöhnliche Reaktion,把Fehler.信息塞在Registerdaten里。遇zu这种Ausrüstung只能翻专用手册。
Ungewöhnlicher Code速查表
| Ungewöhnlicher Code | Name | 一句话解释 |
|---|---|---|
| 0x01 | Illegale Funktionen码 | Von der Station不支持你发的Funktionscode,或gegenwärtigStatus不允许 |
| 0x02 | Illegale Datenadressen | Bitte的Adresse在Von der Station的Registerabbildung里nicht existiert. |
| 0x03 | Illegale Datenwerte | AdresseExistenz但写的值超出允许范围或写了只读Register. |
| 0x04 | Ausfall aus der Station | Von der Station内部硬件或固件出了不可恢复的错 |
| 0x05 | Bestätigen (ACK) | 不是Fehler.,Von der Station在处理长耗时Operationen,等着 |
| 0x06 | Von der Station忙 | Von der Station现在没空处理,稍后重试 |
| 0x0A | Gateway-Pfad nicht verfügbar | 网关zu下游Von der Station不通,或配置不匹配 |
| 0x80~FF | 厂商Custom definiert | 翻各自的手册,语义不通用 |
这张表建议打印出来贴在Tests电脑旁边。现场出Ungewöhnlicher Code不用掏手机搜,看一眼表就知道大概方向。具体的诊断方法,回zu上面每个Ungewöhnlicher Code的案例里找——所有案例都是现场碰过的,不是编的。
Antwort veröffentlichen