
From this article, you will learn about the Modbus RTU protocol, which is widely used in process control systems.
Contents:
- Modbus RTU protocol description
- What are Modbus RTU commands?
- How can I send a Modbus RTU command to read a discrete output? Command 0x01
- How can I send a Modbus RTU command to read a digital input? Command 0x02
- How can I send a Modbus RTU command to read an analog output? Command 0x03
- How can I send a Modbus RTU command to read an analog input? Command 0x04
- How can I send a Modbus RTU command to write a discrete output? Command 0x05
- How can I send a Modbus RTU command to write an analog output? Command 0x06
- How can I send a Modbus RTU command to write multiple discrete outputs? Command 0x0F
- How can I send a Modbus RTU command to write multiple analog outputs? Command 0x10
- What are Modbus request errors?
- Programs for working with the Modbus RTU protocol
- Equipment with Modbus RTU support
Modbus RTU protocol description
Modbus is a communication protocol based on a master–slave architecture. It uses RS-485, RS-422, and RS-232 interfaces, as well as Ethernet TCP/IP networks (Modbus TCP) for data transfer.
The Modbus RTU message consists of the SlaveID (device address), the function code, special data (depending on the function), and the CRC checksum.
| SlaveID | Function code | Special data | CRC |
|---|
If you discard the SlaveID address and the CRC checksum, you get the PDU (Protocol Data Unit).
SlaveID is the address of the device. It can take a value from 0 to 247; addresses from 248 to 255 are reserved.
Data in a module is stored in four tables.
Two tables are read-only and two are read-write.
9,999 values are placed in each table.
| REGISTER NUMBER | REGISTER ADDRESS (HEX) | ACCESS | NAME | TYPE |
|---|---|---|---|---|
| 1–9,999 | 0000 to 270E | read–write | Discrete Output Coils | DO |
| 10,001–19,999 | 0000 to 270E | read | Discrete Input Contacts | DI |
| 30,001–39,999 | 0000 to 270E | read | Analog Input Registers | AI |
| 40,001–49,999 | 0000 to 270E | read–write | Analog Output Holding Registers | AO |
The Modbus message uses the register address.
For example, the first AO holding register has the number 40001, but its address is 0000.
The difference between these two quantities is the “offset”.
Each table has its own offset: 1, 10001, 30001, and 40001.
The following is an example of a Modbus RTU request for obtaining holding register values (AO) from registers #40108 to #40110 with device address 17.
11 03 006B 0003 7687
| 11 | Device address (SlaveID). 17 = 11 hex |
| 03 | Function code |
| 006B | Address of the first register (40108 − 40001 = 107 = 6B hex) |
| 0003 | Number of registers requested (read 3 registers from 40108 to 40110) |
| 7687 | CRC checksum |
In response, the Modbus RTU slave returns:
11 03 06 AE41 5652 4340 49AD
Where:
| 11 | Device address (17 = 11 hex) | SlaveID |
| 03 | Function code | Function Code |
| 06 | Number of following bytes (6 bytes follow) | Byte Count |
| AE | High byte of register value (AE hex) | Register value Hi (AO0) |
| 41 | Low byte of register value (41 hex) | Register value Lo (AO0) |
| 56 | High byte of register value (56 hex) | Register value Hi (AO1) |
| 52 | Low byte of register value (52 hex) | Register value Lo (AO1) |
| 43 | High byte of register value (43 hex) | Register value Hi (AO2) |
| 40 | Low byte of register value (40 hex) | Register value Lo (AO2) |
| 49 | Checksum | CRC value Hi |
| AD | Checksum | CRC value Lo |
The analog output register AO0 has the value AE 41 (hex) or 44,609 in decimal notation.
The analog output register AO1 has the value 56 52 (hex) or 22,098 in decimal.
The analog output register AO2 has the value 43 40 (hex) or 17,216 in decimal.
The AE 41 (hex) value is the 16-bit pattern 1010 1110 0100 0001, which can represent different quantities depending on the interpretation.
The value of register 40108, when combined with register 40109, yields a 32-bit value.
An example of representations:
| View type | Value range | Example in HEX | In decimal form |
|---|---|---|---|
| 16-bit unsigned integer | 0 to 65,535 | AE41 | 44,609 |
| 16-bit signed integer | −32,768 to 32,767 | AE41 | −20,927 |
| two-character ASCII string | 2 char | AE41 | ® A |
| discrete on/off value | 0 and 1 | 0001 | 0001 |
| 32-bit unsigned integer | 0 to 4,294,967,295 | AE41 5652 | 2,923,517,522 |
| 32-bit signed integer | −2,147,483,648 to 2,147,483,647 | AE41 5652 | −1,371,449,774 |
| 32-bit single-precision IEEE floating-point number | 1.2×10−38 to 3.4×10+38 | AE41 5652 | −4.395978 E−11 |
| four-character ASCII string | 4 char | AE41 5652 | ® A V R |
What are Modbus RTU commands?
Here is a table with the codes for reading and writing Modbus RTU registers.
| FUNCTION CODE | WHAT THE FUNCTION DOES | VALUE TYPE | ACCESS TYPE | |
|---|---|---|---|---|
| 01 (0x01) | Read DO | Read Coil Status | Discrete | Read |
| 02 (0x02) | Read DI | Read Input Status | Discrete | Read |
| 03 (0x03) | Read AO | Read Holding Registers | 16 bit | Read |
| 04 (0x04) | Read AI | Read Input Registers | 16 bit | Read |
| 05 (0x05) | Write one DO | Force Single Coil | Discrete | Write |
| 06 (0x06) | Write one AO | Preset Single Register | 16 bit | Write |
| 15 (0x0F) | Multiple DO recording | Force Multiple Coils | Discrete | Write |
| 16 (0x10) | Multiple AO recording | Preset Multiple Registers | 16 bit | Write |
How can I send a Modbus RTU command to read a discrete output? Command 0x01
This command is used to read the values of DO (digital outputs).
The PDU request specifies the start address of the first DO register and the number of required DO values thereafter. In the PDU, DO values are addressed starting from zero.
The DO values in the response are packed into bytes and correspond to bit values.
Bit values are defined as 1 = ON and 0 = OFF.
The least significant bit of the first data byte contains the DO value whose address was specified in the request. The remaining DO values follow in ascending order toward the most significant bit of the byte (i.e., from right to left).
If fewer than eight DO values are requested, the remaining bits in the last byte of the response are filled with zeros (from low to high bit). Byte Count indicates the number of full data bytes in the response.
Example of a DO query from 20 to 56 for device address 17. The address of the first register will be 0013 hex = 19, because addressing starts from 0 (0014 hex = 20; minus one offset gives 0013 hex = 19).
| BYTE (Hex) | REQUEST — Field name | BYTE (Hex) | ANSWER — Field name |
|---|---|---|---|
| 11 | Device address | 11 | Device address |
| 01 | Function code | 01 | Function code |
| 00 | Address of first register (Hi) | 05 | Number of following bytes |
| 13 | Address of first register (Lo) | CD | Register value DO 27–20 (1100 1101) |
| 00 | Number of registers (Hi) | 6B | Register value DO 35–28 (0110 1011) |
| 25 | Number of registers (Lo) | B2 | Register value DO 43–36 (1011 0010) |
| 0E | CRC | 0E | Register value DO 51–44 (0000 1110) |
| 84 | CRC | 1B | Register value DO 56–52 (0001 1011) |
| 45 | CRC | ||
| E6 | CRC | ||
The output states of DO 27–20 are represented by the byte value CD hex (binary 1100 1101).
For DO 56–52, five rightmost bits were requested; the remaining bits are filled with zeros to complete the byte (0001 1011).
| Channels | - | - | - | DO 56 | DO 55 | DO 54 | DO 53 | DO 52 |
|---|---|---|---|---|---|---|---|---|
| Bits | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 1 |
| Hex | 1B | |||||||
How can I send a Modbus RTU command to read a digital input? Command 0x02
This command is used to read the values of digital inputs (DI).
Example of a DI request from registers #10197 to #10218 for device address 17. The address of the first register will be 00C4 hex = 196, because addressing starts from 0.
| BYTE (Hex) | REQUEST — Field name | BYTE (Hex) | ANSWER — Field name |
|---|---|---|---|
| 11 | Device address | 11 | Device address |
| 02 | Function code | 02 | Function code |
| 00 | Address of first register (Hi) | 03 | Number of following bytes |
| C4 | Address of first register (Lo) | AC | Register value DI 10204–10197 (1010 1100) |
| 00 | Number of registers (Hi) | DB | Register value DI 10212–10205 (1101 1011) |
| 16 | Number of registers (Lo) | 35 | Register value DI 10218–10213 (0011 0101) |
| BA | CRC | 20 | CRC |
| A9 | CRC | 18 | CRC |
How can I send a Modbus RTU command to read an analog output? Command 0x03
This command is used to read the values of analog outputs (AO).
Example of an AO request from registers #40108 to #40110 for device address 17. The address of the first register will be 006B hex = 107, because addressing starts from 0.
| BYTE (Hex) | REQUEST — Field name | BYTE (Hex) | ANSWER — Field name |
|---|---|---|---|
| 11 | Device address | 11 | Device address |
| 03 | Function code | 03 | Function code |
| 00 | Address of first register (Hi) | 06 | Number of following bytes |
| 6B | Address of first register (Lo) | AE | Register value Hi #40108 |
| 00 | Number of registers (Hi) | 41 | Register value Lo #40108 |
| 03 | Number of registers (Lo) | 56 | Register value Hi #40109 |
| 76 | CRC | 52 | Register value Lo #40109 |
| 87 | CRC | 43 | Register value Hi #40110 |
| 40 | Register value Lo #40110 | ||
| 49 | CRC | ||
| AD | CRC | ||
How can I send a Modbus RTU command to read an analog input? Command 0x04
This command is used to read the values of analog inputs (AI).
Example of an AI request for register #30009 with device address 17. The address of the first register is 0008 hex = 8, because addressing starts from 0.
| BYTE (Hex) | REQUEST — Field name | BYTE (Hex) | ANSWER — Field name |
|---|---|---|---|
| 11 | Device address | 11 | Device address |
| 04 | Function code | 04 | Function code |
| 00 | Address of first register (Hi) | 02 | Number of following bytes |
| 08 | Address of first register (Lo) | 00 | Register value Hi #30009 |
| 00 | Number of registers (Hi) | 0A | Register value Lo #30009 |
| 01 | Number of registers (Lo) | F8 | CRC |
| B2 | CRC | F4 | CRC |
| 98 | CRC | ||
How can I send a Modbus RTU command to write a discrete output? Command 0x05
This command is used to write one value to a DO (digital output).
The value FF 00 (hex) sets the output to ON.
The value 00 00 (hex) sets the output to OFF.
All other values are invalid and will not affect the output value.
The normal response to such a request is an echo (the request is repeated in the response) and is returned after the DO state has been changed.
Example of a DO write to register #173 for device address 17. The register address will be 00AC hex = 172, because addressing starts from 0.
| BYTE (Hex) | REQUEST — Field name | BYTE (Hex) | ANSWER — Field name |
|---|---|---|---|
| 11 | Device address | 11 | Device address |
| 05 | Function code | 05 | Function code |
| 00 | Address of first register (Hi) | 00 | Address of first register (Hi) |
| AC | Address of first register (Lo) | AC | Address of first register (Lo) |
| FF | Value (Hi) | FF | Value (Hi) |
| 00 | Value (Lo) | 00 | Value (Lo) |
| 4E | CRC | 4E | CRC |
| 8B | CRC | 8B | CRC |
The DO173 output state has changed from OFF to ON.
How can I send a Modbus RTU command to write an analog output? Command 0x06
This command is used to write one value to an analog output (AO).
Example of writing to AO register #40002 for device address 17. The address of the first register will be 0001 hex = 1, because addressing starts from 0.
| BYTE (Hex) | REQUEST — Field name | BYTE (Hex) | ANSWER — Field name |
|---|---|---|---|
| 11 | Device address | 11 | Device address |
| 06 | Function code | 06 | Function code |
| 00 | Address of first register (Hi) | 00 | Address of first register (Hi) |
| 01 | Address of first register (Lo) | 01 | Address of first register (Lo) |
| 00 | Value (Hi) | 00 | Value (Hi) |
| 03 | Value (Lo) | 03 | Value (Lo) |
| 9A | CRC | 9A | CRC |
| 9B | CRC | 9B | CRC |
How can I send a Modbus RTU command to write multiple discrete outputs? Command 0x0F
This command is used to write multiple values to DO (digital outputs).
Example of writing to several DOs for registers #20 to #29 with device address 17. The register address will be 0013 hex = 19, since addressing starts from 0.
| BYTE (Hex) | REQUEST — Field name | BYTE (Hex) | ANSWER — Field name |
|---|---|---|---|
| 11 | Device address | 11 | Device address |
| 0F | Function code | 0F | Function code |
| 00 | Address of first register (Hi) | 00 | Address of first register (Hi) |
| 13 | Address of first register (Lo) | 13 | Address of first register (Lo) |
| 00 | Number of registers (Hi) | 00 | Number of recorded registers (Hi) |
| 0A | Number of registers (Lo) | 0A | Number of recorded registers (Lo) |
| 02 | Number of following bytes | 26 | CRC |
| CD | Byte value DO 27–20 (1100 1101) | 99 | CRC |
| 01 | Byte value DO 29–28 (0000 0001) | ||
| BF | CRC | ||
| 0B | CRC | ||
The answer returns the number of registers recorded.
How can I send a Modbus RTU command to write multiple analog outputs? Command 0x10
This command is used to write multiple values to analog outputs (AO).
Example of writing to AO registers #40002 and #40003 for device address 17. The address of the first register will be 0001 hex = 1, because addressing starts from 0.
| BYTE (Hex) | REQUEST — Field name | BYTE (Hex) | ANSWER — Field name |
|---|---|---|---|
| 11 | Device address | 11 | Device address |
| 10 | Function code | 10 | Function code |
| 00 | Address of first register (Hi) | 00 | Address of first register (Hi) |
| 01 | Address of first register (Lo) | 01 | Address of first register (Lo) |
| 00 | Number of registers (Hi) | 00 | Number of recorded registers (Hi) |
| 02 | Number of registers (Lo) | 02 | Number of recorded registers (Lo) |
| 04 | Number of following bytes | 12 | CRC |
| 00 | Value Hi 40002 | 98 | CRC |
| 0A | Value Lo 40002 | ||
| 01 | Value Hi 40003 | ||
| 02 | Value Lo 40003 | ||
| C6 | CRC | ||
| F0 | CRC | ||
What are Modbus request errors?
If the device receives a request but cannot process it, the device responds with an error code.
The response contains the modified function code: the high-order bit is set to 1.
Example:
| IT WAS | IT BECOME |
|---|---|
| FUNCTIONAL CODE IN REQUEST | Functional error code in response |
| 01 (01 hex) 0000 0001 | 129 (81 hex) 1000 0001 |
| 02 (02 hex) 0000 0010 | 130 (82 hex) 1000 0010 |
| 03 (03 hex) 0000 0011 | 131 (83 hex) 1000 0011 |
| 04 (04 hex) 0000 0100 | 132 (84 hex) 1000 0100 |
| 05 (05 hex) 0000 0101 | 133 (85 hex) 1000 0101 |
| 06 (06 hex) 0000 0110 | 134 (86 hex) 1000 0110 |
| 15 (0F hex) 0000 1111 | 143 (8F hex) 1000 1111 |
| 16 (10 hex) 0001 0000 | 144 (90 hex) 1001 0000 |
Sample request and response with error:
| BYTE (Hex) | REQUEST — Field name | BYTE (Hex) | ANSWER — Field name |
|---|---|---|---|
| 0A | Device address | 0A | Device address |
| 01 | Function code | 81 | Function code with changed high bit |
| 04 | Address of first register (Hi) | 02 | Error code |
| A1 | Address of first register (Lo) | B0 | CRC |
| 00 | Number of registers (Hi) | 53 | CRC |
| 01 | Number of registers (Lo) | ||
| AC | CRC | ||
| 63 | CRC | ||
Explanation of error codes:
| 01 | Function code accepted but cannot be processed. |
| 02 | The data address specified in the request is not available. |
| 03 | The value contained in the request data field is invalid. |
| 04 | An unrecoverable error occurred while the slave attempted to perform the requested action. |
| 05 | The slave has accepted the request and is processing it, but it takes a long time. This response prevents a timeout on the host. |
| 06 | The slave is busy processing the command. The master must repeat the message later when the slave is free. |
| 07 | The slave cannot execute the program function specified in the request (applies to function codes 13 or 14). The master should request diagnostic or error information. |
| 08 | The slave detected a parity error when reading extended memory. The master can repeat the request, but repair is usually required. |
Programs for working with the Modbus RTU protocol
The following programs make it easier to work with Modbus.
DCON Utility Pro — supports Modbus RTU, ASCII, DCON. Download

Modbus Master Tool — supports Modbus RTU, ASCII, TCP. Download

Modbus TCP client — supports Modbus TCP. Download
