- 1. 一、Modbus Exception Response的基本机制
- 2. 1.1 正常Response vs Exception Response
- 3. 1.2 Exception Response的判断逻辑
- 4. 二、11 个标准Exception Code完全Parse
- 5. Exception Code 0x01 — Illegal function(Illegal Function)
- 6. Exception Code 0x02 — Illegal data address(Illegal Data Address)
- 7. Exception Code 0x03 — Illegal data value(Illegal Data Value)
- 8. Exception Code 0x04 — Substation equipment malfunction(Slave Device Failure)
- 9. Exception Code 0x05 — Confirm(Acknowledge)
- 10. Exception Code 0x06 — The slave station equipment is busy(Slave Device Busy)
- 11. Exception Code 0x07 — 否定Confirm(Negative Acknowledge)
- 12. Exception Code 0x08 — 存储器奇even parityError(Memory Parity Error)
- 13. Exception Code 0x0A — Gateway path unavailable(Gateway Path Unavailable)
- 14. Exception Code 0x0B — Gateway target device response failed(Gateway Target Device Failed to Respond)
- 15. 三、Exception Code速查表
- 16. 四、深度故障排查方法论
- 17. 4.1 分层排查法
- 18. 4.2 对比排除法
- 19. 4.3 最小化复现法
- 20. 五、RTU 与 TCP 模式下的异常差异
- 21. 六、编程实现:异常处理的最佳实践
- 22. 七、Frequently Asked Questions FAQ
- 23. Q1: Modbus 从站返回了Exception Code 0x02,但address看起来是正确的,为什么?
- 24. Q2: 为什么从站有时返回正常data,有时返回Exception Code 0x06?
- 25. Q3: Exception Code 0x05 和 0x06 有什么区别?
- 26. Q4: 从站完全不Response(超时),而不是返回Exception Code,该怎么排查?
- 27. 八、总结
Modbus Exception Response码与故障排查完全手册:从 01 到 11 的完整Parse
关键词:Modbus Exception Code、Modbus 故障排查、Modbus Error码、Modbus Exception Code、Modbus 通信故障
在Automation现场,Modbus 通信故障是最让工程师头疼的问题之一。当主站发出Request后,从站返回的不是正常data,而是一个「Exception Response」——这表明通信链路没有问题,但业务逻辑层出现了Error。理解每一个Exception Code的含义、触发条件和排查方法,是每一位自动化工程师的必修课。
本文将从 Modbus protocol specification(V1.1b3)出发,结合真实工业现场案例,深入ParseAll 11 个标准Exception Code的触发机制、排查流程和解决方案。无论您是初次接触 Modbus 的新手,还是希望system化梳理知识的老兵,都能从本文中找到实用的参考。
一、Modbus Exception Response的基本机制
1.1 正常Response vs Exception Response
在 Modbus protocol中,主站(Master/Client)向从站(Slave/Server)sendRequestmessage,从站处理后返回Responsemessage。当一切正常时,Response的function code与Request的function code完全一致:
Request: [slave address] [function code 0x03] [starting address高byte] [starting address低byte] [number of registers高byte] [number of registers低byte] [CRC低] [CRC高]
正常Response: [slave address] [function code 0x03] [byte count] [data...] [CRC低] [CRC高]
当从站无法正常处理Request时,它会将function code的最高位(bit 7)置为 1,并在data area放入一个byte的Exception Code。也就是说,异常function code = Requestfunction code + 0x80。例如,Requestfunction code 0x03 出现异常时,Responsefunction code变为 0x83。
Exception Responsemessage结构(RTU 模式):
[slave address] [function code+0x80] [Exception Code] [CRC低] [CRC高]
示例 - Requestdoes not exist的register address:
Request: 01 03 27 10 00 01 [CRC]
Exception Response: 01 83 02 [CRC]
→ function code 0x83 = 0x03 + 0x80,Exception Code 0x02 = Illegal data address
1.2 Exception Response的判断逻辑
当您在Debug Tools(如 Modbus Poll、ModScan)中看到从站返回的data时,判断是否为Exception Response非常简单:
- ViewResponsefunction code是否大于 0x80(即最高位为 1)
- 如果function code > 0x80,则第二个byte即为Exception Code
- 根据Exception Code查表确定ErrorType
在编程实现中,检测逻辑如下:
// C 语言Exception Response检测示例
if (response_function_code & 0x80) {
uint8_t exception_code = response_data[0];
switch (exception_code) {
case 0x01: // Illegal function码
case 0x02: // Illegal data address
case 0x03: // Illegal data value
// ... 其他Exception Code处理
}
}
二、11 个标准Exception Code完全Parse
Modbus protocol specification定义了 11 个标准Exception Code(0x01 ~ 0x0B)。下面逐一深度Parse每个Exception Code的含义、触发条件、典型Scene和排查方法。
Exception Code 0x01 — Illegal function(Illegal Function)
含义:从站不支持Request的function code。这是最常见的Exception Code之一,通常发生在主站使用了从站未实现的function code时。
典型触发Scene:
- function code超出范围:主站send了function code 0x14(读文件记录),但从站只实现了 0x03、0x04、0x06、0x10
- PLC 型号不支持:部分低端 PLC 只支持 0x03 和 0x06,尝试使用 0x10(写多个register)会返回 0x01
- 设备配置Error:某些设备的 Modbus 实现通过配置switchEnable/禁用function code,如果对应Function被禁用,同样返回 0x01
- 网关转换问题:Modbus TCP 到 RTU 的网关可能不支持某些function code的透传
排查步骤:
- 查阅设备手册,Confirm从站支持哪些function code
- 使用 Modbus Poll 等Tools逐一测试function code,缩小问题范围
- 检查Gateway/Converter的function code过滤配置
- 如果使用自研程序,Confirmfunction code常量定义是否正确
实际案例:某水处理项目中,上位机使用function code 0x17(读/写多个register)Operation施耐德 PM800 电力仪表,始终返回Exception Code 0x01。经查手册发现 PM800 只支持 0x03 和 0x10。解决方案:拆分为先 0x03 读取、再 0x10 写入两步Operation。
Exception Code 0x02 — Illegal data address(Illegal Data Address)
含义:Request的register address在从站中does not exist。这是工程师在debug阶段最容易遇到的Exception Code。
典型触发Scene:
- address偏移Error:PLC 的 Modbus address通常从 0 开始,但上位机配置时可能填了 1 start的address
- register范围越界:Request的starting address + quantity超出了从站的最大register范围
- address映射Error:有些设备使用不同的address映射表(如有些设备 40001 对应内部address 0,有些对应 1)
- data type混淆:32 位浮点数占用 2 个register,如果只Request 1 个register,可能触发越界
排查步骤:
- 使用 0x03 function code,从address 0 开始逐一读取,确定effectiveaddress范围
- Confirm设备手册中的address是「协议address」还是「PLC address」——两者可能相差 1
- 对于 32 位data,确保Request的number of registers为偶数
- 检查message中address的大小端endianness是否正确
Exception Code 0x03 — Illegal data value(Illegal Data Value)
含义:Request中的numerical value在从站的允许范围之外。这不涉及address问题,而是「值」的问题。
典型触发Scene:
- 写入值超出范围:temperature设定值范围为 0~100°C,但主站写入了 150
- number of registers不合法:0x10 function code的「number of registers」field为 0 或超过了从站单次可处理的maximum(通常为 123)
- byte count不匹配:0x10 function code的「byte count」field与「number of registers × 2」不一致
- messageLengthError:整个message的实际Length与报头中声明的Length不符
排查步骤:
- 重点检查 0x10(写多个register)的message结构——这是最容易出错的Scene
- 验证「byte count = number of registers × 2」是否成立
- Confirm写入值是否在设备手册规定的范围内
- 对于 0x06(写单个register),检查写入值的范围(0x0000 ~ 0xFFFF)
Exception Code 0x04 — Substation equipment malfunction(Slave Device Failure)
含义:从站在处理Request时发生了不可恢复的内部Error。这是一个「万金油」Exception Code,表示从站自身出现了严重问题。
典型触发Scene:
- EEPROM/Flash 写入失败:从站将配置写入非易失性存储器时失败
- 传感器故障:从站connect的传感器损坏,无法提供effective读数
- 内部通信故障:从站内部的主控芯片与外设之间的通信异常
- 文件systemError:涉及文件Operation的function code(0x14、0x15)遇到文件system异常
排查步骤:
- 检查从站设备的电源是否稳定
- View从站的 LED 指示灯状态(通常有故障灯)
- 尝试对从站进行断电重启
- 联系设备厂商获取诊断Tools或Firmware update
Exception Code 0x05 — Confirm(Acknowledge)
含义:从站已经接受Request,但需要较长time来处理。这不是一个Error,而是一个「请稍候」的信号。从站正在执行Operation,处理Complete后会返回正常Response。
典型触发Scene:
- EEPROM 写入耗时较长:某些设备的非易失性存储器写入可能需要数百毫秒
- Firmware updateOperation:写入程序存储器需要较长time
- 电机执行动作:从站正在执行物理动作(如阀门switch)
编程建议:主站收到Exception Code 0x05 后,不应立即重试或报错,而应等待适当time后重新轮询。建议使用状态机处理:
// 异步处理ConfirmResponse的状态机
enum { IDLE, WAITING, POLLING } state = IDLE;
void modbus_handler(uint8_t func, uint8_t* data) {
if (func & 0x80) {
if (data[0] == 0x05) {
state = POLLING;
start_poll_timer(500); // 500ms 后重新查询
}
}
}
Exception Code 0x06 — The slave station equipment is busy(Slave Device Busy)
含义:从站正在处理一个耗时较长的命令,暂时无法Response新的Request。与 0x05 的区别在于:0x05 是「我在处理你刚发的Request」,0x06 是「我现在没空处理任何Request」。
典型触发Scene:
- 从站在执行耗时Operation:如Firmware update、大量data拷贝
- 从站 CPU 负载过高:硬件性能有限,无法及时处理 Modbus Request
- 从站正在进行自诊断:部分设备在启动时会执行自检,期间不Response通信
排查步骤:
- 适当增加主站的轮询间隔(如从 100ms 增加到 500ms)
- 减少同时通信的从站quantity
- 检查从站的固件版本,Confirm是否有已知的性能问题
Exception Code 0x07 — 否定Confirm(Negative Acknowledge)
含义:从站无法执行Request中的编程Function。这是专门为 0x0D(编程Function)设计的Exception Code,表示编程Request被拒绝。
典型触发Scene:
- 编程RequestType不支持:从站的编程Function有限,不支持特定的编程Operation
- 编程参数Invalid:Request中包含了不支持的编程参数
Precautions:Exception Code 0x07 在 Modbus protocol specification V1.1b3 中定义,但实际上绝大多数 Modbus 设备并不实现function code 0x0D(编程),因此这个Exception Code在现实中极少遇到。
Exception Code 0x08 — 存储器奇even parityError(Memory Parity Error)
含义:从站在读取文件记录时,检测到存储器奇even parityError。仅与文件Operationfunction code(0x14、0x15)Related。
典型触发Scene:
- 文件记录损坏:文件存储区域因电源故障或其他原因data损坏
- Flash 存储器老化:频繁写入导致 Flash 存储单元的可靠性下降
Exception Code 0x0A — Gateway path unavailable(Gateway Path Unavailable)
含义:网关无法建立到目标设备的内部通信路径。这通常发生在网关connect了多个下游设备时。
典型触发Scene:
- 下游设备离线:网关后的 Modbus RTU 设备断电或断开connect
- 下游Device addressError:网关被配置为转发到does not exist的slave address
- 网关内部路由表Error:网关的路由配置不正确
排查步骤:
- 检查网关下游设备的通信状态指示灯
- 使用 Modbus Poll 直接connect下游设备,排除设备本身故障
- 检查网关的路由表配置
- Confirm下游设备的 Modbus address和Baud rate设置
Exception Code 0x0B — Gateway target device response failed(Gateway Target Device Failed to Respond)
含义:网关能够建立通信路径,但目标设备未能提供effectiveResponse。与 0x0A 的区别:0x0A 是网关内部路径不通,0x0B 是路径通了但目标设备无Response。
典型触发Scene:
- 目标设备繁忙:设备正在处理上一条指令
- 目标设备Response超时:Modbus RTU 的 3.5 字符超时机制触发
- data format不匹配:下游设备的Communication parameters(Baud rate、校验方式)与网关设置不一致
三、Exception Code速查表
| Exception Code | 名称(英文) | 名称(中文) | 常见程度 |
|---|---|---|---|
| 0x01 | Illegal Function | Illegal function | ★★★★★ |
| 0x02 | Illegal Data Address | Illegal data address | ★★★★★ |
| 0x03 | Illegal Data Value | Illegal data value | ★★★★☆ |
| 0x04 | Slave Device Failure | Substation equipment malfunction | ★★★☆☆ |
| 0x05 | Acknowledge | Confirm(等待中) | ★★★☆☆ |
| 0x06 | Slave Device Busy | The slave station equipment is busy | ★★★☆☆ |
| 0x07 | Negative Acknowledge | 否定Confirm | ★☆☆☆☆ |
| 0x08 | Memory Parity Error | Memory verification error | ★☆☆☆☆ |
| 0x0A | Gateway Path Unavailable | Gateway path unavailable | ★★☆☆☆ |
| 0x0B | Gateway Target Failed | 网关目标Response失败 | ★★☆☆☆ |
四、深度故障排查方法论
4.1 分层排查法
工业通信故障排查应遵循「自底向上」的原则,从物理层逐步向上层排查:
- 物理层:检查线缆connect、终端电阻、设备供电、接地情况
- data链路层:使用示波器或逻辑分析仪检查 RS-485 信号质量
- 网络层:在 Modbus TCP Scene下,使用 Wireshark 抓包分析
- 应用层:使用 Modbus Poll 等Toolssend最小化Request来定位问题
4.2 对比排除法
当现场有多个同型号设备时,使用对比排除法是最高效的定位手段:
- 将疑似故障设备与正常工作equipment交换位置
- 使用同一台主站Tools分别测试两台设备
- 比较两台设备的Responsemessage差异
4.3 最小化复现法
将复杂Request简化为最简单的合法Request,逐步增加复杂度:
步骤 1: send最简Request 01 03 00 00 00 01 [CRC] —— 读取address 0 的 1 个register
步骤 2: 如果成功,逐步增加number of registers 00 02, 00 03 ...
步骤 3: 如果失败,缩小address范围排查
五、RTU 与 TCP 模式下的异常差异
虽然Exception Code的定义在 RTU 和 TCP 模式下完全一致,但两种模式下的异常处理流程有所不同:
| 对比维度 | Modbus RTU | Modbus TCP |
|---|---|---|
| 超时处理 | 3.5 字符time无Response判定超时 | TCP connect超时由Operationsystem控制 |
| 异常检测 | CRC verificationError直接丢弃message | TCP 层保证data完整性 |
| MBAP 报头 | 无 | 需要检查Transaction identifier匹配 |
| 网关Scene | 较少涉及 | Exception Code 0x0A/0x0B 更常见 |
六、编程实现:异常处理的最佳实践
以下是使用 C 语言实现 Modbus 异常处理的完整示例,适用于嵌入式system开发:
/**
* Modbus Exception Code处理函数
* @param func Requestfunction code
* @param exception Exception Code
* @return 人类可读的Error描述字符串
*/
const char* modbus_exception_str(uint8_t func, uint8_t exception) {
static char buf[128];
const char* exc_name;
switch (exception) {
case 0x01: exc_name = "Illegal function码"; break;
case 0x02: exc_name = "Illegal data address"; break;
case 0x03: exc_name = "Illegal data value"; break;
case 0x04: exc_name = "Substation equipment malfunction"; break;
case 0x05: exc_name = "Confirm(等待中)"; break;
case 0x06: exc_name = "The slave station equipment is busy"; break;
case 0x07: exc_name = "否定Confirm"; break;
case 0x08: exc_name = "Memory verification error"; break;
case 0x0A: exc_name = "Gateway path unavailable"; break;
case 0x0B: exc_name = "网关目标Response失败"; break;
default: exc_name = "Unknown exception code"; break;
}
snprintf(buf, sizeof(buf),
"Modbus 异常: function code 0x%02X → Exception Code 0x%02X (%s)",
func, exception, exc_name);
return buf;
}
/**
* 处理 Modbus Response
* 返回 0 表示正常Response,负值表示异常
*/
int modbus_handle_response(uint8_t* rsp, int rsp_len,
uint8_t expected_func) {
if (rsp_len < 2) return -1; // ResponseLength异常
uint8_t func = rsp[1]; // RTU 模式下,第二个byte是function code
if (func & 0x80) {
// Exception Response
uint8_t exception = rsp[2];
log_error(modbus_exception_str(func & 0x7F, exception));
// 根据Exception Code采取不同的重试策略
switch (exception) {
case 0x01: // function code不支持 - 不重试
case 0x02: // address非法 - 不重试
return -exception;
case 0x05: // Confirm - 等待后重试
case 0x06: // 设备忙 - 延迟重试
return -exception; // 调用者处理重试逻辑
default:
return -exception;
}
}
// 正常Response处理...
return 0;
}
七、Frequently Asked Questions FAQ
Q1: Modbus 从站返回了Exception Code 0x02,但address看起来是正确的,为什么?
最常见的原因是「address偏移 1」的问题。某些设备(特别是 PLC)的 Modbus address与协议addressexistence 1 的偏移。比如 PLC 端配置address为 40001,但 Modbus protocol中对应的内部address是 0(而不是 1)。请查阅设备手册Confirmaddress映射关系。
Q2: 为什么从站有时返回正常data,有时返回Exception Code 0x06?
这通常意味着从站的 CPU 处理能力不足。当轮询频率过高时,从站来不及处理所有Request,就会返回 0x06。解决方法:降低轮询频率,或减少单次Request的number of registers。
Q3: Exception Code 0x05 和 0x06 有什么区别?
0x05(Confirm):从站已经在处理你send的特定Request,需要等待Complete。0x06(设备忙):从站当前无法处理任何新Request,原因可能是任意Operation。简单记忆:0x05 是「你的事我在办」,0x06 是「我现在很忙谁都别来」。
Q4: 从站完全不Response(超时),而不是返回Exception Code,该怎么排查?
完全无Response通常意味着问题在物理层或data链路层:
- 检查slave address是否正确(address不匹配是从站静默的最常见原因)
- 检查 RS-485 的 A/B 线是否接反
- 检查Baud rate和校验方式是否匹配
- 检查终端电阻和偏置电阻
- 使用示波器Confirm总线上是否有信号
八、总结
Modbus 的Exception Response机制是协议设计中的一大亮点——它不是简单地让通信失败,而是通过Exception Code精确地告诉主站「哪里出了问题」。掌握这些Exception Code的含义和排查方法,可以将故障定位time从数小时缩短到数分钟。
建议将本文的Exception Code速查表打印出来贴在工位旁,或者在Debug Tools中集成Exception Code自动ParseFunction。在工业现场,每一分钟的停机都意味着真金白银的损失——而快速定位 Modbus Exception Code,往往是解决问题的第一步。
Related阅读:Modbus function code完全Parse | Modbus RTU 与 TCP 深度对比 | Modbus CRC verification原理与编程实现
发表回复