Detailed Explanation of Modbus-RTU Message Structure and Common Function Codes
Modbus is a serial communication protocol that was published by Modicon (now Schneider Electric) in 1979 for communication with programmable logic controllers (PLCs). The Modbus protocol has now become the industry standard for communication protocols in the field of industrial control and is commonly used for communication between industrial electronic devices.
The reason why the Modbus protocol has become the most widely used protocol in the field of industrial control is due to the following characteristics:
- • Open Architecture: The Modbus protocol is completely open and has no copyright restrictions, allowing companies to freely modify it to adapt to their devices, thus reducing development costs. After Schneider Electric made the protocol public, over 200 companies worldwide launched compatible hardware;
- • Cross-Platform Compatibility: Supports various physical layer interfaces such as RS-485, RS-232, and Ethernet, covering scenarios from serial communication to TCP/IP networks;
- • Simple and Stable Protocol: Fixed data frame format (Address + Function Code + Data + CRC) and master-slave communication mode ensure real-time performance and reliability;
Modbus RTU Protocol
1. Basic Concepts of Modbus RTU Protocol
The Modbus RTU mode is a binary mode where data is transmitted byte by byte, with the high bit of each byte sent first. During data transmission, an error detection mechanism is used to ensure data integrity. Typically, the RTU mode communicates via RS-485 bus, as it supports multiple devices (up to 247 devices) and long-distance transmission.
2. Frame Structure of Modbus RTU Communication
| Purpose |
Length |
Description |
| Device Address |
1 byte |
The slave has a unique address, ranging from 1 to 247. Address 0 is a broadcast address, and the slave will not respond. |
| Function Code |
1 byte |
The type of operation requested by the master for the slave to perform. |
| Data |
Variable (0-252 bytes) |
Contains specific parameters of the command, with format and length depending on the function code. |
| CRC Check |
2 bytes |
Checks for errors in the data during transmission. |
3. Function Codes in Modbus RTU Protocol
Common Function Code Table
| Function Code |
Name |
Data Type |
Function |
| 0x01 |
Read Coils |
Bit |
Obtains the current status (ON/OFF) of a group of logical coils. |
| 0x02 |
Read Discrete Inputs |
Bit |
Obtains the current status (ON/OFF) of a group of switch inputs. |
| 0x03 |
Read Holding Registers |
Integer, Float, Character |
Obtains the current binary value from one or more holding registers. |
| 0x04 |
Read Input Registers |
Integer, Float |
Obtains the current binary value from one or more input registers. |
| 0x05 |
Write Single Coil |
Bit |
Forcibly sets the ON/OFF state of a logical coil. |
| 0x06 |
Write Single Register |
Integer, Float, Character |
Loads a specific binary value into a holding register. |
| 0x0F |
Write Multiple Coils |
Bit |
Forcibly sets the ON/OFF state of a series of continuous logical coils. |
| 0x10 |
Write Multiple Registers |
Integer, Float, Character |
Loads specific binary values into a series of continuous holding registers. |
1. Function Code 0x01 – Read Coils
- • Function: Reads the coil registers of the slave, bit operation, can read single or multiple;
- • Send Command: Slave Address: 0x01, Register Start Address: 0x0017, read a total of 8 coils. The command sent is as follows:
| Slave Address |
Function Code |
Register Start Address (High 8 bits) |
Register Start Address (Low 8 bits) |
Register Count (High 8 bits) |
Register Count (Low 8 bits) |
CRC H |
CRC L |
| 0x01 |
0x01 |
0x00 |
0x17 |
0x00 |
0x08 |
0x8D |
0xC8 |
Tx:01 01 00 17 00 08 8D C8
- • Response: Returns the corresponding coil status for each bit of data, where 1 indicates ON and 0 indicates OFF;
| Slave Address |
Function Code |
Returned Byte Count |
Data |
CRC H |
CRC L |
| 0x01 |
0x01 |
0x01 |
0x17 |
0x11 |
0x86 |
Rx:01 01 01 17 11 86
2. Function Code 0x02 – Read Discrete Inputs
- • Function: Reads the discrete input registers of the slave, bit operation, can read single or multiple;
- • Send Command: Slave Address: 0x01, Register Start Address: 0x0017, read a total of 8 coils. The command sent is as follows:
| Slave Address |
Function Code |
Register Start Address (High 8 bits) |
Register Start Address (Low 8 bits) |
Register Count (High 8 bits) |
Register Count (Low 8 bits) |
CRC H |
CRC L |
| 0x01 |
0x02 |
0x00 |
0x17 |
0x00 |
0x08 |
0xC9 |
0xC8 |
Tx:01 02 00 17 00 08 C9 C8
- • Response: Returns the corresponding coil status for each bit of data, where 1 indicates ON and 0 indicates OFF;
| Slave Address |
Function Code |
Returned Byte Count |
Data |
CRC H |
CRC L |
| 0x01 |
0x02 |
0x01 |
0x17 |
0xE1 |
0x86 |
Rx:01 02 01 17 E1 86
3. Function Code 0x03 – Read Holding Registers
- • Function: Reads the holding registers of the slave, byte operation, can read single or multiple;
- • Send Command: Slave Address: 0x01, Register Start Address: 0x0017, read a total of 1 register. The command sent is as follows:
| Slave Address |
Function Code |
Register Start Address (High 8 bits) |
Register Start Address (Low 8 bits) |
Register Count (High 8 bits) |
Register Count (Low 8 bits) |
CRC H |
CRC L |
| 0x01 |
0x03 |
0x00 |
0x17 |
0x00 |
0x01 |
0x34 |
0x0E |
Tx:01 03 00 17 00 01 34 0E
- • Response: Returns data;
| Slave Address |
Function Code |
Returned Byte Count |
Data1H |
Data1L |
CRC H |
CRC L |
| 0x01 |
0x03 |
0x02 |
0x17 |
0x01 |
0x76 |
0x74 |
Rx:01 03 02 17 01 76 74
4. Function Code 0x04 – Read Input Registers
- • Function: Reads the input registers of the slave, byte operation, can read single or multiple;
- • Send Command: Slave Address: 0x01, Register Start Address: 0x0017, read a total of 1 register. The command sent is as follows:
| Slave Address |
Function Code |
Register Start Address (High 8 bits) |
Register Start Address (Low 8 bits) |
Register Count (High 8 bits) |
Register Count (Low 8 bits) |
CRC H |
CRC L |
| 0x01 |
0x04 |
0x00 |
0x17 |
0x00 |
0x01 |
0x81 |
0xCE |
Tx:01 04 00 17 00 01 81 CE
- • Response: Returns data;
| Slave Address |
Function Code |
Returned Byte Count |
Data1H |
Data1L |
CRC H |
CRC L |
| 0x01 |
0x04 |
0x02 |
0x17 |
0x01 |
0x77 |
0x00 |
Rx:01 04 02 17 01 77 00
5. Function Code 0x05 – Write Single Coil
- • Function: Writes a single coil, bit operation, can only write one, writing 0xFF00 indicates the coil is ON, writing 0x0000 indicates the coil is OFF.
- • Send Command: Slave Address: 0x01, set coil 0x0017 to ON. The command sent is as follows:
| Slave Address |
Function Code |
Register Start Address (High 8 bits) |
Register Start Address (Low 8 bits) |
DATAH |
DATAL |
CRC H |
CRC L |
| 0x01 |
0x05 |
0x00 |
0x17 |
0xFF |
0x00 |
0x3C |
0x3E |
Tx:01 05 00 17 FF 00 3C 3E
- • Response: Same as sent data;
6. Function Code 0x06 – Write Single Register
- • Function: Writes a single holding register, byte operation, can only write one;
- • Send Command: Slave Address: 0x01, set register 0x0017 to 0x2193. The command sent is as follows:
| Slave Address |
Function Code |
Register Start Address (High 8 bits) |
Register Start Address (Low 8 bits) |
DATAH |
DATAL |
CRC H |
CRC L |
| 0x01 |
0x06 |
0x00 |
0x17 |
0x21 |
0x93 |
0x61 |
0xF3 |
Tx:01 06 00 17 21 93 61 F3
- • Response: Same as sent data;
7. Function Code 0x0F – Write Multiple Coils
- • Function: Writes multiple coil registers, where bit 0 in the data area indicates OFF, and bit 1 indicates ON;
- • Send Command: Slave Address: 0x01, coil address 0x0012, write 5 coils. The command sent is as follows:
| Slave Address |
Function Code |
Register Start Address (High 8 bits) |
Register Start Address (Low 8 bits) |
Register Count (High 8 bits) |
Register Count (Low 8 bits) |
Byte Count |
DATAH |
DATAL |
CRC H |
CRC L |
| 0x01 |
0x0F |
0x00 |
0x12 |
0x00 |
0x05 |
0x01 |
0x00 |
0x13 |
0x54 |
0x93 |
Tx:01 0F 00 12 00 05 01 00 13 54 93
| Slave Address |
Function Code |
Register Start Address (High 8 bits) |
Register Start Address (Low 8 bits) |
Register Count (High 8 bits) |
Register Count (Low 8 bits) |
Byte Count |
CRC H |
CRC L |
| 0x01 |
0x0F |
0x00 |
0x12 |
0x00 |
0x05 |
0x01 |
0xCC |
0xD7 |
Tx:01 0F 00 12 00 05 01 00 13 CC D7
8. Function Code 0x10 – Write Multiple Registers
- • Function: Writes multiple holding registers, byte operation, can write multiple;
- • Send Command: Slave Address: 0x01, register address 0x0012, write 2 registers with 4 bytes of data. The command sent is as follows:
| Slave Address |
Function Code |
Register Start Address (High 8 bits) |
Register Start Address (Low 8 bits) |
Register Count (High 8 bits) |
Register Count (Low 8 bits) |
Byte Count |
DATA1H |
DATA1L |
DATA2H |
DATA2L |
CRC H |
CRC L |
| 0x01 |
0x10 |
0x00 |
0x12 |
0x00 |
0x02 |
0x04 |
0x00 |
0x13 |
0x00 |
0x11 |
0x42 |
0xB3 |
Tx:01 0F 00 12 00 05 01 00 13 00 11 42 B3
| Slave Address |
Function Code |
Register Start Address (High 8 bits) |
Register Start Address (Low 8 bits) |
Register Count (High 8 bits) |
Register Count (Low 8 bits) |
Byte Count |
CRC H |
CRC L |
| 0x01 |
0x10 |
0x00 |
0x12 |
0x00 |
0x02 |
0x04 |
0x0C |
0x8B |
Tx:01 0F 00 12 00 02 04 0C 8B
Conclusion
The Modbus RTU protocol is a very common communication protocol in industrial control systems, widely used for serial communication between various devices due to its simplicity, reliability, and efficiency. It is suitable for small to medium-sized systems, especially playing an important role in communication between field devices, PLCs, and sensors. However, due to the lack of built-in security mechanisms, it is necessary to ensure the security of the network and communication when using it.
Recommended Tools
- • Free online tool Modbus RTU Message Parser
- • Free online tool Modbus TCP Message Parser
- • Free online tool Modbus ASCII Message Parser
- • Useful! Hexadecimal to Float Online Tool