What is the abnormal frame length like
The difference between Modbus abnormal response and normal response is only one bit. After the master station sends a request, the slave station places the highest position of the function code at 1, followed by a single byte exception code, and the frame ends. There is no data area.
Structural comparison between normal frames and abnormal frames:
请求: 01 03 00 00 00 01 — 读 1 号站,保持寄存器 0x0000
正常响应: 01 03 02 12 34 — 02=数据字节数,0x1234=读回的值
异常响应: 01 83 02 — 83=0x03|0x80,02=异常码 0x02The example above shows that the highest position 1 of function code 0x03 becomes 0x83. Exception code 0x02 represents' illegal data address' - indicating that the address 0x0000 does not exist in the slave station.
Take a closer look at CRC verification: Regardless of whether the response is normal or abnormal, CRC is calculated from the station address to the last data byte (excluding CRC itself). I intentionally didn't write CRC above, but there are actually two bytes left at the end of the frame.
The difference between RTU and TCP exception frames lies in the encapsulation layer. The MBAP header of TCP contains a 2-byte 'length' field, which includes the unit identifier, function code, and exception code. And RTU separates frames by a 3.5-character silence time. The protocol layers are different, but the semantics of function codes and exception codes are exactly the same - this is one of the cleanest designs of Modbus.
Another detail that is easily overlooked is that the frame length of abnormal responses is fixed. For function codes 0x01~0x06, the exception response is always only 3 bytes (address+function code | 0x80+exception code), and CRC is calculated separately. For multi operation function codes such as 0x0F and 0x10, the exception response is also 3 bytes. The slave does not need to tell you 'which part went wrong', only 'the entire request was rejected'. This design is rough, but also simple - after receiving an exception code, the main station tries to retry or report an error on its own.
The timing at the serial port level also requires attention to detail. Modbus RTU stipulates that the slave must start responding within a specified time after receiving a request - but the standard does not specify a specific value for this time. In practice, the response time of most slave stations is between 5-50ms. If no response is received for more than 1 second (or no exception frame is received), the master station should consider the slave station to be unresponsive - this is a timeout, not an exception code. Many industrial control software mix "No Response" and "Exception Response" together to give you the illusion that the device has returned an exception code. In fact, there was no response from the station. Distinguishing between these two situations is crucial for troubleshooting - the lack of response is a problem at the link layer or device layer, and the exception code is when the slave application layer tells you 'I received it but I'm not doing it'.
Below, we will break down 7 types of standard exception codes one by one. Each one is equipped with real messages and on-site cases - not captured through Wireshark simulation, but encountered in production lines, substations, and pump rooms.
0x01- Illegal Function Code
The slave station does not support the function code requested by the master station, or the function code is disabled in the current state of the slave station.
If you send a 0x08 diagnostic function code to a standard Modbus device that supports 03/06/16, there is a high probability that you will receive 0x01. Because diagnostic function codes are optional, many inexpensive I/O modules have not been implemented at all.
Message Example
请求: 02 08 00 00 AA 55
异常响应: 02 88 010x08=Diagnosis, Subcode 0x0000=Loop Test, Data 0xAA55. Return directly from the station to 0x88 (0x08 | 0x80)+0x01.
Case 1: Delta DVP series PLC does not support diagnostic function codes
Delta DVP-SX2 series, firmware version V3.8. In the project, we conducted RS-485 line quality testing and used the Modbus Poll Test Center to send 0x08 diagnosis, which resulted in the return of exception code 0x01. After reviewing the DVP manual, it was confirmed that DVP only implemented six function codes, 01/03/05/06/0F/10, and 0x08 was not included in its list. To diagnose the quality of the circuit, one can only use 0x01 to read the coil or 0x03 to read the register, and indirectly judge through response time and continuous success rate. This incident tells us that although diagnostic function codes are written into the Modbus standard, not all manufacturers are convinced.
Case 2: Siemens S7-1200 does not support coil reading when using Modbus Server
Siemens S7-1200 supports Modbus TCP Server starting from TIA Portal V14. But its implementation only maps DB blocks to hold registers (0x03/0x06/0x10), and coils 0x01/0x05/0x0F are not done at all. When debugging with the upper computer, SCADA uses 0x01 to read the device status word, and S7-1200 directly throws back a 0x81+0x01. Solution: Map the coil address to the hold register section and switch to 0x03 read on the upper computer.
Case 3: Prohibiting parameter writing during frequency converter operation
Huichuan MD500 frequency converter, attempting to write frequency setting register 0x2000 using 0x06 while in operation. Return 0x01. It's not that the frequency converter doesn't support the 0x06 function code, but the current state doesn't allow writing. In Huichuan's manual, this is referred to as' run write prohibited ', but the protocol layer uses the standard exception code 0x01. This semantic extension can be seen on many domestic devices - using standard exception codes to express manufacturer defined constraints.
Case 4: Modbus Plus specific function code rejected on TCP gateway
An old Modicon Quantum PLC converts Modbus Plus to Modbus TCP through a BM85 bridge. Modbus Plus has its own set of extended function codes (0x14~0x18 for network management), but the BM85 bridge only transmits standard Modbus function codes transparently. The upper computer accidentally sent a request to read PLC statistical information at 0x14, and the bridge returned 0x81+0x01 directly after checking at the application layer. Note that the exception code returned here is from the gateway, not the PLC - PLC may support 0x14, but the gateway does not. There is no parsing route for this function code in the bridge log, so it was rejected directly. It is common for gateways to perform function code security filtering in practical projects, especially for industrial routers with firewall functionality.
0x02- Illegal data address
The slave station supports this function code, but the requested starting address+quantity exceeds the valid address range of the slave station. This is the most common exception code encountered during on-site debugging, without a single one.
Key point: There is an offset between the address filled in the main station software and the actual address sent by the protocol layer. The Modbus protocol stipulates that addresses are numbered starting from 0. The 40001 (1-based hold register) you filled in Modbus Poll is 0x0000 sent by the protocol layer. The address calculation logic is reversed, which can result in reading incorrect data or triggering 0x02 in severe cases.
PLC/SCADA 地址表示: 40001 (1-based, 保持寄存器)
协议层 PDU 地址: 0x0000 (0-based)Message Example
请求: 01 03 00 64 00 0A — 读 0x0064 = 400101,读 10 个
异常响应: 01 83 02The effective holding register range of the slave station is 40001-40090 (i.e. PDU address 0x0000~0x0059), and the requested starting address 0x0064 is exceeded, so it is directly 0x02.
Case 1: Insufficient Schneider TM3 expansion module address
Schneider Modicon M221 is equipped with two TM3 extensions. The first TM3DI16 in the configuration accounts for% IW0~% IW1, and the second TM3AI4 accounts for% IW2~% IW5. The upper computer SCADA uses 0x04 (read input register) to read% IW10, and the slave station returns 0x02. The reason is simple - M221 only allocated% IW0~% IW5, and% IW10 is not in the physical I/O mapping. Just take a glance at the I/O mapping table in SoMachine and you'll understand. This issue is a mismatch between configuration and actual hardware, not a protocol defect.
Case 2: Pits for Modbus Poll addresses 40001 and 400001
A novice engineer copied the address 40001 from the Modbus Poll table, but the Modbus Poll actually sent 0x0000 and read the first hold register of the device. No problem. But later on, another domestic configuration software was used, which parsed 40001 into an offset of 4000+1, but the actual output was 0x0FA0. The slave station doesn't have that many registers, so return 0x02. The same point table and the same slave station have different software address conventions for different master stations, resulting in different outcomes. This is not a problem with the Modbus protocol, it is caused by the conventions of each player in the toolchain. Suggest communicating directly with colleagues using PDU addresses (0-based), not to mention zones 4 and 5, as they are all based on Modicon's old almanac.
Case 3: End address out of bounds when reading multiple registers
A Modbus meter with 64 registers (0x0000~0x003F). The main station requests to read 10 registers (0x0038~0x0041) starting from 0x0038. Slave check: The last address 0x0038+9=0x0041>0x003F, throw 0x02 directly. When checking the legitimacy of addresses, many stations first calculate whether the starting and quantity are within the range, and reject the entire package as long as any address exceeds the limit. It is not a register that returns partial data out of bounds - the Modbus standard does not have the concept of partial response.
Case 4: Confusion between Discrete Input and Coil Address
This pitfall is particularly common in companies that use Modicon's old-fashioned 5-digit address labeling. 1xxxx is the discrete input (read-only bit), and 0xxxx is the coil (read-write bit). The upper computer configuration has configured address 10001 to read the device status, but in reality, the slave station should have placed the device status in the coil area (0xxxx corresponds to 0x01 function code). The upper computer uses 0x02 (read discrete input) to request address 0x0000, but 0x0000 does not exist in the discrete input area in the slave station - there are a total of 8 discrete inputs (addresses 0x0000~0x0007), but those 8 have already been allocated to other DIs. The slave station returns 0x02. Changing the function code or address can solve the problem, but the prerequisite is that you need to know what the address mapping table of the slave station looks like. Many industrial control engineers directly map all discrete signals to the coil area or to the hold register, saving users from confusion - but only if your slave station allows you to do so.
0x03- Illegal data value
The address is valid and the function code is valid, but the data value carried in the request body is not within the allowed range.
This is an easily overlooked exception code. Many times, you may suspect that the address configuration is incorrect, but in reality, the value written is out of bounds.
Message Example
请求: 01 06 00 10 FF FF — 写单个寄存器,地址 0x0010,值 0xFFFF
异常响应: 01 86 03 — 功能码 0x06|0x80 = 0x86,异常码 0x03Why is 0xFFFF (65535) illegal? Because that register has an engineering value range of 0 to 10000. 65535 is valid in 16 bit representation, but not valid in business logic.
Case 1: Writing EEPROM parameters outside the configuration range
Omron E5CC thermostat, register 0x0103 (PID proportional band). The valid range of this parameter is 0.1~999.9, stored in units of 0.1 ° C, with register values ranging from 1 to 9999. The upper computer issues 0x0000 (i.e. 0.0 ° C), and after verification by the slave station, it is found that the value is less than the lower limit of 1, and 0x03 is returned. The manual specifies the scope, but the upper computer code was lazy and did not perform boundary checks. It took half an hour to realize that the value was written out of range - a low-level mistake that everyone makes, it's important to remember to read the manual first and then check the exception code.
Case 2: Performing write operations on read-only registers
ABB ACS580 frequency converter, register 0x2104 (actual speed feedback, read-only). The upper computer attempted to write 1500 using 0x06 (to manually provide the speed value), and the slave station returned 0x03. The address 0x2104 itself exists and the function code 0x06 is also supported, but this address is marked as read-only within the slave station. The meaning of 'illegal data value' here is' you wrote data to an address that does not accept writing '- it is not the value itself that is illegal, but the writing action is illegal. In the Modbus protocol specification, the wording of 0x03 is' Value is not allowed ', giving the slave implementation degrees of freedom. Many manufacturers classify read-only protection under 0x03.
Case 3: Multiple Register Write - Some Field Values are Illegal
Write 5 registers in batches using 0x10. The first 4 values are fine, but the 5th register requires a value between 0 and 100. You wrote 200. Some slave stations will verify all data before replying, execute 5 valid ones, and reject any invalid one as a whole and return 0x03. Some sub stations verify one by one and reject the first one if it is found to be illegal. The standard does not specify which method must be followed, and the implementation varies among different companies. I suggest you conduct a boundary test on the device you are using to have a clear understanding.
Case 4: Demand Reset Register Permission Control of Modbus Meter
Schneider PM800 series power meters, register 0x2F01 (demand reset command) can only write specific control word combinations (0x1234 or 0x5678). The upper computer mistakenly wrote 0x0001 attempting to clear the demand, and the instrument returned 0x03. The manual clearly states that the valid values for the reset command register are 0x1234 and 0x5678, and any other value triggers 0x03. This design is to prevent misoperation - after all, some registers writing errors are not as simple as reporting errors, they can actually change parameters.
There is also a trap related to 0x03: when function code 0x06 writes to a single register, if the register is the lower 16 bits of a 32-bit value, only the lower 16 bits are written and the upper 16 bits are not initialized, the slave station may return 0x03. For example, for the parameter 0x1000 (32-bit floating-point) of AB ACS580, you must write two registers at once using 0x10 and cannot split them into two 0x06. If written separately, the slave will report 0x03 at the first 0x06- because it knows that this address is 32-bit aligned and does not accept 16 bit write operations.
0x04- Slave device failure
An irreparable internal error occurred while processing the request, causing the command to fail to execute. This exception code tells you that 'it's not your request that's wrong, it's me who broke it myself'.
0x04 is the most tense exception code on site. 0x01~0x03, you can solve it by changing the configuration. 0x04 means you may have to climb a ladder in the workshop.
Message Example
请求: 03 03 00 20 00 04 — 读 4 个保持寄存器
异常响应: 03 83 04The same request, which returned data normally ten minutes ago, is now continuously returning 0x04. The possibility of hardware failure is high.
Case 1: Modbus sensor EEPROM write failure
A Kunlun Coast JWSK-6 temperature and humidity transmitter with Modbus RTU interface. I remotely changed the device address from 0x01 to 0x05, and there was a power jitter during the process of writing to EEPROM. Write failed, device firmware detected EEPROM checksum mismatch and entered fail safe mode. Afterwards, all function code requests (whether reading 0x03 or writing 0x06) will return 0x04. After checking the manual, it was confirmed that the sensor will lock communication after EEPROM self-test failure, and can only be physically powered off and restarted to restore factory settings. This belongs to firmware protection mechanism - stronger than letting you read error values.
Case 2: Short circuit of temperature controller probe causing abnormal AD conversion
The RKC CB100 thermostat has a short circuit at the thermocouple input due to water ingress at the wiring terminal. The AD conversion chip reads an overflow value, and the firmware determines that the sensor is faulty. Then, all requests to read PV values with 0x03 return 0x04. This 0x04 is not a Modbus communication chip failure, it is a sensor front-end fault reflected to the protocol layer through the firmware's abnormal transmission mechanism. I replaced the thermocouple and wiped the terminals dry, but 0x04 disappeared.
Case 3: Expansion I/O module disconnection
Siemens ET200SP uses an interface module to create a Modbus TCP Server. A DI module disconnected due to poor contact of the backplane connector. For the register address of the disconnected module, the slave station uniformly returns 0x04. But the register addresses of other normal modules are read normally. This indicates that the internal fault isolation of the substation is done well - a broken part does not affect the overall situation.
Case 4: Overvoltage protection triggered for analog input module
Advantech ADAM-4117 analog input module, with a range set from 0 to 5V. An unexpected 12V signal was connected to a certain channel, and the overvoltage protection circuit in the module was activated, causing the channel to enter a fault state. All requests to read the channel value 0x04 return 0x04, and the configuration file displays the location of the error flag. Disconnect the overvoltage signal and restore it after powering on again. The root cause of 0x04 is in the physical wiring, not in the communication protocol. When troubleshooting, the wires were first disconnected, and then simulated signals were used for testing - but I remember that ADAM-4117 sometimes needs a soft reset, and simply re powering on is not enough.
0x05- Confirm (ACK)
0x05 is not an error. It says from the slave station to the master station, "Got it, we're working on it. Don't rush for now
The standard wording is' Acknowledge '. The slave station has accepted the request, but it takes a long time to process (such as writing Flash or performing self-tuning). First, return a 0x05 to let the master station know that the connection is not disconnected. After the subsequent processing is completed, inform the result through a normal response or status bit.
This is the most special one among the 7 standard exception codes - it is the only exception code that does not indicate a problem.
Message Example
请求: 01 06 0F A0 00 00 — 写寄存器 0x0FA0 = 0x0000,触发参数保存
异常响应: 01 86 05Case 1: Writing frequency converter parameters into EEPROM
Delta VFD-M frequency converter, writing 0x2000 (command register)=0x0010 triggers the 'parameter write to EEPROM' operation. The EEPROM erase cycle is around 10-30ms. After receiving the command from the slave station, it first returns 0x86+0x05, indicating "I know you want to save the parameters and are writing Flash". After about 20ms, the command register can be polling again, and reading 0x0000 indicates that the write is complete. If it is not completed within 50ms after 0x05, some frequency converters will time out and roll back.
Case 2: PID self-tuning of temperature controller
Omron E5CC, write 0x0101 (AT execution/stop)=0x0001 to start self-tuning. This operation will take a few minutes. E5CC first returns to 0x05, and then during the self-tuning process, PV and SV values can be read normally, except that the AT flag is ON. After self-tuning is completed, AT automatically turns off. The upper computer needs to start a timeout timer after receiving 0x05, don't just wait there - some devices have self-tuning capabilities that can run for 30 minutes.
Case 3: Slow response of slave stations in the gateway backend
Modbus TCP to RTU gateway (such as MOXA MGate MB3170), the master reads a slave on a 9600bps low-speed bus through the gateway. The master station sent a request to read 125 registers, and the gateway forwarded this request to the RTU bus. However, due to the large amount of data and low baud rate, the RTU slave station needs 200ms+to complete the data response. Before receiving a complete RTU response, the gateway first sends a 0x05 placeholder to the TCP master station - this is the common "pending" processing method used by gateways. The Modbus TCP specification does not explicitly specify the usage of 0x05 in this scenario, but many gateway manufacturers do so.
A design detail to note: the waiting strategy on the main station side after 0x05 is triggered. The same request should not be resent immediately - this will result in the slave receiving duplicate commands. The correct approach is to poll a status register (if provided by the slave) or set a timeout timer, and send a new query command after timeout. Some SCADA drivers (such as Kepware's Modbus driver) have built-in processing logic for 0x05, while others directly report timeouts. If you write your own Modbus driver, the processing logic for 0x05 is a mandatory task.
0x06- Slave Station Busy
The station is currently too busy to handle your request. The command was accepted but cannot be executed. The main station should retry later.
The difference between 0x05 and 0x06: 0x05 means' received, processing, waiting for result '; 0x06 means' I'm not available now, come back later '. 0x05 means that the slave has already started executing commands, while 0x06 means that the slave has not started executing at all.
Message Example
请求: 01 06 20 00 07 D0 — 写寄存器 0x2000 = 0x07D0(2000)
异常响应: 01 86 06 — 忙,没空处理Case 1: Read immediately after writing the parameters
After writing a parameter that requires writing EEPROM, immediately send the next request within 10ms. The slave Flash controller has not yet released the bus and is directly returning 0x06. Many engineers send consecutive requests every few milliseconds during script debugging, leaving the slave station with no time to process them. It's not that the device is slow, it's that you're too fast. Modbus does not have a flow control mechanism, and the master station needs to control the pace itself - after writing the Flash related registers, leave 30-50ms before sending the next read/write request.
Case 2: High speed polling causes low-speed device buffer overflow
Use Modbus Poll to poll a 9600bps RTU temperature and humidity sensor at 20ms intervals. At the beginning, it was normal, but after running for one minute, intermittent 0x06 appeared. Transferring one byte at 9600bps takes about 1ms, and a minimum read request+response round-trip takes about 30-40ms. The 20ms polling interval is already less than the minimum response period of the device. The receiving buffer of the slave serial port is filled up, and it is busy discarding overflow frames, with no energy to process new requests. Just adjust the polling interval to 100ms. Switching to 115200bps can further shorten the speed, but many industrial control devices only support up to 38400bps or even 19200bps.
Case 3: Multiple master stations accessing a slave station simultaneously
A Modbus RTU slave station on an RS-485 bus is connected to both PLC and SCADA master stations. There is no coordination between the two main stations, and they poll at intervals of 500ms and 300ms respectively. The collision probability has increased - two request frames overlap, and the slave station receives garbled code. Some slave stations ignore frame errors when they are detected, while others consume time to handle errors, resulting in the next master station frame arriving just after clearing the receive buffer. Not ready to receive new frames yet, can only reply with 0x06. For conflict handling of RS-485 multi master stations, it is recommended to implement hardware flow control or implement mutex locks on the master station side, rather than relying on the slave station to handle it on its own.
Case 4: Receiving a request during the initialization period of power on from the station
Most Modbus slave stations have initialization times ranging from tens of milliseconds to a few seconds after being powered on. Make a request in this window, the Modbus protocol stack of the slave station is not ready yet. Some slave stations do not respond directly, while others return 0x06. This behavior is related to the specific firmware implementation. The Danfoss VLT FC302 frequency converter will return 0x06 within approximately 2 seconds after power on, and will return to normal after initialization is complete. If your SCADA starts reading from the slave station, the first few requests may receive 0x06- adding a power on delay in the upper computer code or automatically retry 0x06 (with an interval of 500ms, up to 3 times) can avoid it.
0x06 and 0x05 are easily confused. Let's make it clear: 0x05 is' processing your request 'and will return normal data after processing. 0x06 means' There is no time to process your request, the request has been discarded '. The main station should wait upon receiving 0x05, and retry upon receiving 0x06. If 0x06 is treated as 0x05- wait and wait, it will time out.
0x0A - Gateway path unavailable
This exception code only appears in gateway scenarios. There is a communication issue between the gateway and downstream slave stations - the gateway itself is fine, but the devices behind it cannot connect.
The wording defined by the Modbus standard is' Gateway Path Unavailable '- unable to establish a path to the target device. The target device here is not the slave body with address 0x01, but the path from the "router" inside the gateway to the downstream slave.
Message Example
请求: 01 03 00 00 00 01 — 通过网关读下游从站
异常响应: 01 83 0A — 网关:后面那个从站没响应Case 1: Slave disconnection in the backend of a serial server
The USR-N510 serial server is used as a Modbus TCP to RTU gateway, with three Modbus RTU sensors (addresses 0x01, 0x02, 0x03) attached below. 0x02 The slave is completely disconnected due to a burnt power module. When the master station read 0x02 from the slave station through the gateway, the serial server attempted to broadcast the request on the RS-485 bus, but did not receive a response after a timeout of 500ms. Then, it returned 0x0A to the master station on the TCP side. The communication between 0x01 and 0x03 slave stations is completely normal - the gateway itself is alive, only one path is broken.
Case 2: Gateway configured with incorrect downstream parameters
MOXA MGate MB3170, Configure downstream to 9600bps and 8N1. But in reality, the devices on the RS-485 bus are 19200bps and 8E1 (even parity). The gateway sends request frames at 9600bps, but the slave station receives garbled code and does not respond. The gateway returns 0x0A after timeout. This problem is particularly common on RS-485 buses with multiple devices mixed together - the default communication parameters of different manufacturers are different, and if not adjusted uniformly in the early stages of the project, it will cause pitfalls.
Case 3: Modbus TCP Cascade Gateway
A large distributed scenario: central SCADA → Modbus TCP master gateway → fiber ring network → local sub gateway → RS-485 slave station. The fiber between the main gateway and the sub gateway is broken, and all requests from the slave stations under the sub gateway are returned with 0x0A by the main gateway. At this point, the troubleshooting approach is to ping step by step: first confirm the TCP connection from the main gateway to the sub gateway, then confirm the connection from the sub gateway to the RS-485 bus, and finally the serial device itself.
Manufacturer defined exception code
In addition to the 7 standard exception codes, many manufacturers have defined private exception codes in the range of 0x80~0xFF. This is not a violation of the standard - the Modbus specification allows manufacturers to extend it. But if your upper computer code only recognizes 01~0A, it will report an "Unknown Exception" or directly lose frames when encountering 0x90.
Some common vendor extensions:
| manufacturer | Custom Exception Code | meaning |
|---|---|---|
| Siemens S7-1200/1500 | 0x80 | Modbus Server DB block not initialized |
| Huichuan AM600 | 0x81 | Parameter locking (requires writing unlock register first) |
| Delta AS Series | 0x8B | Function code is disabled in the current PLC operating mode |
| Partial domestic temperature controllers | 0x90~0x9F | Parameter verification failed (write value does not match EEPROM) |
| Schneider M221 | 0xF0 | Register regions not supported by firmware |
There is no unified standard for these exception codes, so we need to go through the manuals of each company. Some manufacturers list complete exception codes in the Modbus communication section of their manuals, some hide them in the appendix, and some simply do not write them - you can only debug and judge based on experience after catching them.
There is a pitfall: Some domestic PLCs also return 0x03 when encountering the 0x02 condition (without distinguishing between illegal addresses and illegal data values), because their internal exception handling categorizes "address does not exist" and "value is illegal" as the same error route. You expected 0x02 according to the standard, but actually received 0x03- don't be too serious, just check the register mapping table in the manual.
Another easily overlooked issue is the behavior of exception codes in CPU shutdown mode. Many PLCs still run the Modbus protocol stack in STOP state, but their behavior is different. When the Siemens S7-1200 is used as a Modbus Server, the CPU switches from RUN to STOP and reads the mapped DB block, returning 0x04 ("device failure") instead of 0x01. This semantics is subtle - the PLC is not broken, but DB data is unavailable in STOP mode. Schneider M221 still responds to Modbus requests in STOP state, but the data is not updated. When Mitsubishi FX5U is used as a Modbus Server, it does not respond to any requests directly in the STOP state. The upper computer sees a timeout, not an exception code. The same SCADA system needs to adapt to the STOP behavior of different brands of PLCs, and the driver level needs to be differentiated.
Vendor extended exception codes are often used in security scenarios. For example, some gateway devices that support Modbus Security (based on TLS) will return custom exception codes 0xE0~0xEF to indicate security layer rejection when authentication fails. This is not defined by the Modbus standard, but it does exist. If your Modbus TCP communication suddenly starts receiving 0xE1, it's not a protocol stack parsing error, it's the gateway telling you 'TLS handshake failed'.
Capture abnormal frames with Wireshark
Whether RTU or TCP, Wireshark can directly parse the Modbus protocol. The premise is that your packet capture point is at the correct network location.
TCP scenario
Modbus TCP goes through port 502, Wireshark parses by default. Enter 'modbus' in the filter bar, and abnormal frames will be displayed with a red background.
Expand the exception response frame and look at these key fields:
Modbus/TCP
Transaction Identifier: 1
Protocol Identifier: 0
Length: 3 ← 注意这个长度
Unit Identifier: 1
Modbus
Function Code: 131 (0x83) ← 83 = 03 | 0x80,Wireshark 直接显示了
Exception Code: 2 (Illegal Data Address)`Length: 3 'is the length field in the MBAP header, which=Unit Identifier (1)+Function Code (1)+Exception Code (1)=3 bytes. The normal response value will be larger (because there is data later). Just by looking at the length, one can preliminarily determine whether it is an abnormal response or a normal response - the TCP payload of an abnormal response is usually only 3 bytes.
RTU scenario
RTU packet capture requires the use of an RS-485 to USB converter to build a monitoring node. Wireshark's support for RTUs is not as good as TCP and requires manual specification of port configurations (baud rate, parity, etc.). The captured abnormal frame format is similar to TCP, but without MBAP header:
01 83 02 xx xx — 地址 01,功能码 83,异常码 02,CRC xx xxThere is no Transaction ID in the RTU packet capture, so you can only rely on timestamps to determine the correspondence between requests and responses. When debugging complex multi slave RTU buses, it is recommended to filter by Modbus address in Wireshark and separate the traffic of each slave.
Wireshark's Modbus parser supports Chinese display of exception codes starting from version 3. x. Check the Exception resolution option in Preferences → Protocols → Modbus. However, please note that Wireshark can only parse standard exception codes 01-0A, and vendor specific codes will display numbers instead of descriptive text.
There is also a Wireshark tip: use 'modbus. perception_comde' as a display filter. `Modbus.exe==2 ` Filter out all 0x02 exception frames. `Modbus.exe>=1&&modbus.exe<=10 ` Filter all standard exceptions. When conducting on-site inspections, first look at the global statistics - Statistics → Protocol Hierarchy → Modbus, and you can see the percentage of abnormal frames in the total communication volume. If the number of abnormal frames exceeds 10%, there is a high probability that there is a problem with your configuration. If there are only occasional 0x06, it is a timing issue. If 0x04 persists, prepare to replace the device.
Exception prompts in Modbus Poll
Modbus Poll is the most commonly used debugging tool. Its abnormal information is directly displayed in the status bar at the bottom of the window, which looks like this:
Modbus Exception Response
Function: 3, Exception: 2 (Illegal Data Address)Don't panic when you first see the red text, first look at what the Function is, and then look at what the Exception is. The function code tells you which operation reported an error, and the exception code tells you why.
Open Display → Communication to see the complete transmission and reception of messages. Abnormal frames are marked in red, click to see the original hexadecimal:
Tx: 01 03 00 00 00 01 84 0A
Rx: 01 83 02 C0 F1`The second byte of Rx 'is 0x83 (=0x03 | 0x80), and the third byte 0x02 is the exception code. `C0 F1 'is CRC. Modbus Poll can help you parse it out, but learning to read raw frames on your own is a basic skill - you won't always have Modbus Poll available after deployment online.
Continuously reporting 0x02 for the same request, do not change the address for now. First, confirm if your starting address and quantity are within the valid range listed in the slave manual. Many times it's because the address calculation logic is wrong, not because you wrote the wrong address. Especially when switching from a 1-based register address to a 0-based PDU address - this pitfall is something that almost every beginner has to step on once.
Debugging methodology: Checklist for troubleshooting after receiving exception codes
There was an abnormal code on site. Follow the following sequence - it's not a standard operating procedure, it's the experience of an experienced engineer.
**Step 1: Confirm which slave, which function code, and which exception code it is**
Because there is usually more than one slave station on site. Use Modbus Poll or Wireshark to capture the original message and obtain three numbers: slave address, function code, and exception code. If you are testing with a script, add a line 'print (hex (response [0]), hex (response [1]), hex (response [2])' instead of just looking at the 'communication failure' in the log.
**Step 2: Exception code classification - software or hardware reasons? **
0x01/0x02/0x03 is most likely an issue with your request. Check configuration, address mapping, and data range. 0x04/0x0A is most likely a problem with the slave station or link. Power off and restart the slave station first - if 0x04 becomes normal, it means that the device has recovered from an internal fault, but it does not mean that the root cause has been resolved. 0x06 is a timing issue, slow down the polling interval.
**Step 3: Isolate variables**
Try using a different slave address for the same master station. Can communicate → The problem lies with the original slave station. Unable to communicate → The problem lies in the main station or bus. Try using Modbus Poll with the same slave address. There is a problem with your upper computer code that can communicate. Unable to communicate → There is a problem with the slave station or link. This is the most common binary search method, but many people skip this step and directly suspect that the hardware is broken.
**Step 4: Refer to the manual**
The exception code is out, please refer to the Modbus communication chapter in the slave station manual. Some manufacturers will list all possible exception codes and triggering conditions that may be returned. If there is no abnormal code table in the manual, look for the address mapping table and manually compare whether your requested address is within the valid range. Many on-site 'communication failures' are actually caused by you reading a reserved address or only writing the address.
**Step 5: Capture the package**
Use Wireshark or serial monitoring tools to capture raw packets. What you're looking at is: What exactly did the main station send out? What did the website reply to? Is there a CRC error? Is there any incomplete frame? Many times, when you look at the logs and think it was sent to 01 03 00 00 01, you actually catch the packet and find that the baud rate is incorrect. The slave station throws it away as noise. Don't trust your code logs, trust packet capture tools.
**Step 6: Replace Test**
Connect a new slave station of the same model and see the results for the same request. If the new device is functioning properly, the original device will return an exception code indicating a hardware malfunction. If the new device also returns the same exception code - there is a problem with your request. If you don't have a backup device on hand, use a reliable slave address to test the communication link. The suspicion of the link has been ruled out, and the problem lies with the specific device.
**Step 7: If you still can't figure it out**
Send the original message (hexadecimal), slave model and firmware version, and your master platform information to the FAE of the slave manufacturer. Don't send screenshots of logs, send the original message - FAE is much more accurate in reading the original message than in reading your description. If FAE doesn't reply, go to the modbus.cn forum and post the original message for help. The debugging experience of the community is sometimes more reliable than the manufacturer's manual, because the manual is theory, and the community is tears and blood.
**Addendum: Template for handling exception codes when writing Modbus drivers by oneself**
If you are writing a Modbus master driver for the upper computer (using C/Python/Node.js, etc.), exception frame handling should cover at least these situations:
1. Check if the first byte of the response is equal to the requested slave address (address mismatch=not the response given to you, discard)
The wrong approach is to treat all exception codes as' communication failure 'and retry -0x02. Trying 10000 times is also 0x02, and if the address is wrong, it is wrong. The correct approach is to adopt different strategies based on the classification of exception codes. Once this logic is written, your driver will be able to adapt to 90% of Modbus slave devices on the market. The remaining 10% are manufacturers who do not return exception codes according to standards - they replace exception responses with normal responses and stuff error messages into register data. When encountering such equipment, one can only refer to the dedicated manual.
Exception Code Quick Check Table
| Exception Code | Name | One sentence explanation |
|---|---|---|
| 0x01 | Illegal function code | The slave does not support the function code you sent, or the current status does not allow it |
| 0x02 | Illegal data address | The requested address does not exist in the register mapping of the slave station |
| 0x03 | Illegal data value | The address exists but the written value exceeds the allowed range or a read-only register is written |
| 0x04 | Substation equipment malfunction | An unrecoverable error occurred in the internal hardware or firmware of the slave station |
| 0x05 | Confirm (ACK) | It's not an error, just standing there and dealing with time-consuming operations, waiting |
| 0x06 | Busy from the station | The slave station is currently unavailable for processing. Please try again later |
| 0x0A | Gateway path unavailable | Gateway to downstream slave station not accessible, or configuration mismatch |
| 0x80~FF | Manufacturer customization | Flipping through their respective manuals, the semantics are not universal |
It is recommended to print out this table and paste it next to the debugging computer. If an abnormal code appears on site, you don't need to search on your phone. You can tell the general direction with just a glance at your watch. The specific diagnostic method can be found in each case of abnormal code above - all cases were encountered on site, not fabricated.
发表回复