Hello everyone, I am Mai Ge. I previously wrote an article about the modbus
protocol, which was just a simple introduction. In this article, we will delve deeper into the modbus RTU
protocol.
1. Background
Before introducing modbus rtu
, we can understand that Modbus
was invented by Schneider Electric in 1979 and is the world’s first truly industrial bus protocol. Over the past forty years, it is still widely used in various industrial control fields.
In addition to the stability of this protocol:
-
Free; -
Easy to deploy and maintain; -
For vendors, there are not many restrictions on modifying local bits or bytes.
modbus
is an application layer messaging protocol on the seventh layer of the OSI
model, which defines the hierarchy of open systems, the interrelationships between layers, and the possible tasks included in each layer, serving as a framework to coordinate and organize the services provided by each layer.
The OSI
reference model does not provide a method for implementation, but describes some concepts for coordinating the formulation of inter-process communication standards. Thus, the OSI
reference model is not a standard but a conceptual framework used in the formulation of standards.
modbus
can be described in the OSI
model as shown below:

EIA485
/TIA485
refers toRS485
. With the continuous development of technology, the 485 standard is currently maintained by the Telecommunications Industry Association (TIA), hence the name TIA-485. Of course, it is also acceptable for engineers and application guidelines to continue referring to it as RS-485;
Next, we will introduce some serial link protocols.
2. Modbus Serial Link Protocol
The Modbus
serial link protocol is a master-slave mode (host and slave), half-duplex data transmission protocol. The 485 standard generally requires two wires, and at a certain moment, a host and a slave communicate.
-
Master-slave mode: Generally, there is one host and multiple slaves on the bus, each slave has a unique ID, and the host addresses the slave via the ID for data transmission; -
Half-duplex transmission: In contrast to half-duplex is full-duplex, where full-duplex operates with sending data and receiving data occurring simultaneously, making half-duplex easy to understand as it can only either send or receive data at the same time;
The overall structure diagram is as follows:

Here we need to clarify a few points:
-
The slave cannot actively send data to the slave; it can only send data back to the host after receiving data from the host (sending request); specifically as follows:

As mentioned earlier, modbus
is half-duplex, meaning that while the host is sending data, it cannot receive data. Thus, this process is divided into two steps:
-
The host can send data in two ways: one-to-one or one-to-many, which is commonly referred to as broadcasting, where all slaves can receive the data sent by the host;
One-to-one only requires sending data to a specific address of the slave, while broadcasting only requires setting the sending address to 0, thus the broadcast address is 0.
Here we have a general understanding of the data transmission situation between the host and the slave. Next, we will introduce the specific format of data transmission.
3. Transmission Modes

First, there are two transmission modes for Modbus: RTU transmission mode and ASCII transmission mode.
-
RTU transmission:
Remote Terminal Unit
mode consists of messages in hexadecimal, with high data density and throughput; -
ASCII transmission: Messages are sent as ASCII characters, which are less efficient than RTU mode and are used when the timing management of RTU mode cannot be utilized.
For example:
0x12
will be combined into two characters for sending:0x31
and0x32
,because
0x31
equals character 1;0x32
equals character 2
Next, we will focus on modbus RTU
.
4. Frame Format
Before discussing the frame format, let’s imagine a conversation between people, where the most basic unit is a character, and they communicate using sentences composed of characters, such as in the following dialogue:
-
The boss asks: What to eat for lunch? -
Little Zhang says: Let’s eat!

Thus, communication between machines is similar; we can consider bytes as the most basic data unit, which then form sentences, i.e., communication frames;
However, the situation changes when there is another person in the conversation, besides Little Zhang, such as Little Hong. In this case, to clarify who is speaking to whom, we need to add names at the beginning of the conversation:
-
The boss: Little Zhang, are we having noodles for lunch? -
Little Zhang: Boss, let’s go eat. -
Little Hong, not being called, is left out.

Therefore, returning to the modbus
data frame format, the protocol defines a simple protocol data unit (PDU) for a basic communication layer, as shown in the figure below:

Thus, it is essentially divided into four parts: Address Field, Function Code, Data, Error Check (CRC/LRC), collectively referred to as ADU (Application Data Unit
). Basically, all data to be transmitted must meet this format to be considered a complete frame. Comparing this to the earlier dialogue with the boss, we can simply understand the following:
-
Address Field: Can be understood as who to talk to; -
Function Code: Can be understood as specific action, such as go do, come take, go eat, etc.; -
Data: Can be understood as specific content, such as noodles, rice, etc., or other items, based on context, hence it refers to food; -
Error Check: Can be understood as ensuring that what is said must be understandable; otherwise, others won’t understand it. In practice, CRC or LRC is usually used in the protocol to ensure that the transmitted data is error-free.
Next, we will analyze this further.
(1) PDU
Modbus PDU (protocol data unit
) format is defined as a function code followed by a set of associated data.
The size and content of the data are defined by the function code, and the total size of the PDU (function code and data) cannot exceed 253 bytes.
Each function code has a specific behavior, and the slave can flexibly implement these behaviors based on the application requirements.
The PDU specification defines the core concepts for data access and operation; however, the slave may handle data in ways not explicitly defined in the specification.
(2) Address Field
The address field occupies one byte, so generally, the addressing range is 0~255
, typically 1~147
is used in systems, with other addresses temporarily reserved. Additionally, each address on the same bus must be unique for the slave.
Among them, 0
is a broadcast address.
Below is a sample initialization code for a slave in Freemodbus, where 0x02
is the address of this slave.
eMBInit(MB_RTU, 0x02, 3, 115200, MB_PAR_NONE);
(3) Function Code
The function code occupies one byte, so the range is 0~255
. The protocol classifies function codes into three categories: public function codes, user-defined function codes, and reserved function codes. The overall classification is as follows:

Public function codes must ensure their uniqueness, which has been established by the Modbus organization and includes consistency testing for function codes, thus ensuring the reusability of the protocol to some extent.
From the above table, it can be seen that public function codes are divided into four types:
-
Discrete Input: Read-only type, unit: bit
; -
Coil: Read-write type, unit: bit
; -
Input Register: Read-only type, unit: byte; -
Holding Register: Read-write type, unit: byte.
Below are the callback functions required for handling these four public function codes on the slave when porting the Freemodbus protocol:
// Input register quantity
eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
eMBErrorCode eStatus = MB_ENOERR;
return eStatus;
}
// Holding register quantity
eMBErrorCode
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs,
eMBRegisterMode eMode )
{
eMBErrorCode eStatus = MB_ENOERR;
return eStatus;
}
// Coil quantity
eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,
eMBRegisterMode eMode )
{
eMBErrorCode eStatus = MB_ENOERR;
return eStatus;
}
// Discrete input quantity
eMBErrorCode
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
eMBErrorCode eStatus = MB_ENOERR;
return eStatus;
}
5. How Data is Transmitted at the Lower Level
First, let’s look at how the lowest level modbus data is sent. Yes, upon seeing RS485 and 232, we naturally think of serial ports.
Thus, the fundamental data format can refer to the definition of serial port data, which includes start bit, data bits, parity bit, and stop bit; specifically as follows:

Therefore, we can stipulate:
Start bit + Data bits + Parity bit (optional) + Stop bit equals one character; thus, we can calculate the time required for a single character using the baud rate of the serial port.
Next, let’s look at how modbus frames are sent?
In RTU
mode, the interval between frames must be at least 3.5 character times to indicate the start and end of the frame, so to implement a modbus rtu
, a timer is needed to calculate the length of the idle time.

3.5 Character Time
All data must be sent as a continuous stream of characters; if the length between two characters equals 1.5 character times, it is deemed that the frame message is incomplete, and the device should not accept the message, as shown below:

1.5 Character Time
It is important to note that RTU requires the participation of timer interrupts. Therefore, the detection of 1.5 character time and 3.5 character time, especially at high serial communication speeds, requires high-frequency interrupts, which increases system overhead.
Thus, typically when the baud rate is below 19200
, the specifications for 1.5 and 3.5 character times can be strictly adhered to.
If the baud rate exceeds 19200
, then two fixed times must be satisfied:
-
1.5 Character Time: 750us -
3.5 Character Time: 1.75ms
6. Conclusion
This article briefly introduced the modbus rtu
protocol, including serial link communication, frame format, and the message format at the hardware link layer. Due to limited capacity, there may be errors and omissions in this article; please feel free to point them out. Due to space constraints, this article ends here. The next article will introduce how to port the Freemodbus protocol and the debugging process of the protocol.
If this article has helped you, please give a thumbs up to encourage me.

END
Source: Uncle Mai
Copyright belongs to the original author. If there is any infringement, please contact for deletion.
▍Recommended Reading
Is Keil Restricted from Selling in China?
Deep Exploration of Struct in Embedded C Language
What is the Difference Between Hex and Bin Files in Microcontrollers?