RS485 Communication with STM32 using MAX485 Module
RS485 is one of the most widely used communication standards in industrial and embedded systems because it allows reliable long-distance and multi-device communication. Unlike UART, which is limited to short-distance point-to-point communication, RS485 supports differential signaling, making it noise-resistant and capable of working over longer cables.
In this tutorial, we will interface the RS485 MAX485 module with STM32 microcontrollers. You will learn the wiring connections, CubeMX configuration, and how to use UART to enable RS485 communication. By the end, you will have a working example project that demonstrates data transfer between STM32 and another RS485 device.
Recommended Resources:
The RS485 communication is performed using the UART peripheral of STM32. I have already covered a series on the UART peripheral and you must check out the related tutorials before continuing here.
In this tutorial, we will demonstrate how to interface the RS485 to TTL converter module with an STM32 microcontroller. Two STM32 boards—specifically the STM32F103 and STM32F446—will be used for this setup. These boards will communicate with each other through the RS485 modules, showcasing a practical implementation of half-duplex serial communication.
By the end of this guide, you will understand how to use STM32 and ESP8266 together for MQTT communication and build a solid base for more advanced IoT projects like sending sensor data, subscribing to topics, or using RTOS for message handling.
STM32 RS485 Communication Video Tutorial
This tutorial demonstrates how to interface the RS485 MAX485 module with STM32 microcontrollers. I’ve prepared both a detailed written guide and a practical video walkthrough. Watch the video while following the code here to clearly understand the wiring, CubeMX setup, and UART configuration for RS485 communication in real time.
Watch the RS485 STM32 TutorialIntroduction to RS485 Communication
What is RS485 and why use it in STM32 projects?
RS485 is a serial communication standard that uses differential signaling to transmit and receive data. Unlike simple UART communication, which works best for short distances and only between two devices, RS485 is designed for long-distance, reliable, and multi-device communication. It can support cable lengths of up to 1200 meters and allows multiple devices (up to 32 or more) to share the same communication bus.
In STM32 projects, RS485 is often used in industrial automation, sensor networks, motor controllers, and smart energy meters where multiple devices need to communicate reliably over long distances in electrically noisy environments. The STM32 microcontroller, combined with an external transceiver like the MAX485 module, makes it easy to implement RS485 communication while still using the familiar UART peripheral.
Advantages of RS485 over UART communication
While UART is simple and effective for short-range, point-to-point communication, it has limitations when it comes to distance, noise immunity, and device count. RS485 solves these issues by offering:
- Long-distance communication – RS485 supports reliable data transfer up to 1200 meters, whereas UART is usually limited to just a few meters.
- Multi-drop capability – Unlike UART, which connects only two devices, RS485 allows multiple devices (master-slave or multi-master) to share the same bus.
- Noise immunity – RS485 uses differential signaling, meaning the data is transmitted as the voltage difference between two wires (A and B). This makes it highly resistant to noise and ideal for industrial environments.
- Higher data integrity – Because of its noise resistance and differential signaling, RS485 ensures fewer errors in data transmission compared to UART, especially in harsh electrical conditions.
In short, RS485 extends the capabilities of UART by enabling longer distance, robust, and scalable communication, which is why it is widely used in STM32-based industrial and embedded projects.
RS485 MAX485 Module Overview
An RS485 to TTL converter is a communication interface module that allows microcontrollers, like STM32, to communicate over long distances using the RS485 protocol. It converts the differential RS485 signals into standard TTL-level serial data, which can be read by UART peripherals on microcontrollers. RS485 is known for its robustness, noise immunity, and ability to support multiple devices on the same bus, making this converter ideal for industrial and embedded systems applications.
These modules often use the MAX485 transceiver chip, which supports half-duplex communication and is capable of driving long cable lengths with high reliability.
Important Features of RS485 to TTL Converter:
- Differential Signaling for Long-Distance Communication: It uses differential signal transmission, which reduces noise and allows data to be transmitted over distances of up to 1200 meters.
- Multi-Device Bus Support: RS485 supports up to 32 devices on the same communication line, enabling multi-node communication in a single network.
- Wide Voltage Compatibility: Operates on a 5V power supply and provides TTL-level output compatible with 3.3V or 5V microcontrollers.
- Driver/Receiver Enable Pins (DE/RE): The DE and RE pins allow precise control of data direction, essential for implementing half-duplex communication between devices.
The signal level used during the RS485 communication method typically ranges from -7V to +12V. The microcontroller pins are generally not designed to handle these levels. This is why these signals needs to be converted to low voltages, for eg ±3V. The module have the MAX485 chip on it, which does most of the job of conversion.
RS485 Module Pinout
The pinout of the module is shown below
On the left side of the module, the RO pin connects to the RX pin of the UART, and the DI pin connects to the TX pin.
The RE and DE Pins are responsible for setting the module in Receiver or Transmitter mode.
- When the RE pin is LOW and DE pin is LOW, the Module is set in the Receiver mode.
- When the DE pin is HIGH and RE pin is HIGH, the Module is set in the Transmitter mode.
The Pin A and the Pin B are the output pins which carries the transmission signal.
Let’s take an example where we provide the data, 0x95 (10010101) to the module. If the Module is powered with 5V, the output on pins A and B will be as shown below
- Since A is the non-inverting pin, it’s output will be in sync to the input. It varies between 0 to +5V
- B is the inverting pin, so the output is inverted and varies between -5V to 0
- When the second module receives these as inputs, it decode the data based on the voltage differences.
- If the voltage difference is maximum, the bit is 1, and if the difference is 0 the bit is 0
- This data is then converted to lower voltages (0 to 3V) to suit the MCU requirement
STM32 and RS485 Wiring Connections
Below is the connection diagram of the module with the STM32F103C8 controller. The connection will remain same with the F446 also, so I am just showing one of them here.
As demonstrated above, the RO (Receiver Output) pin of the MAX485 module is connected to PA10, which serves as UART1 RX on the STM32. The DI (Driver Input) pin is connected to PA9, configured as UART1 TX.
The RE (Receiver Enable) and DE (Driver Enable) pins are tied together and connected to PA8, which is configured as a digital output on the STM32. This setup allows the microcontroller to control whether the module is in transmit or receive mode.
MAX485 Pin | Function | STM32 Pin | Notes |
---|---|---|---|
RO | Receiver Output | PA10 | UART1 RX |
DI | Driver Input | PA9 | UART1 TX |
RE | Receiver Enable | PA8 | Tied with DE, output control |
DE | Driver Enable | PA8 | Tied with RE, output control |
VCC | Power Supply | 5V/3.3V | According to module specs |
GND | Ground | GND | Common ground |
STM32 CubeMX Configuration for RS485
Before writing the code for RS485 communication, it is essential to properly configure the STM32 peripherals using CubeMX.
The UART configuration in the CubeMX is shown below.
UART1 is configured with its default settings, using a baud rate of 115200 and 8-N-1 format (8 data bits, no parity, 1 stop bit). Additionally, the UART receive interrupt has been enabled to allow the STM32 to receive data from the second controller asynchronously.
The Pins used for this project are shown below.
The PA8 pin is configured as a digital output and renamed TX_EN. It controls the MAX485 module’s mode: high for transmit and low for receive, allowing the STM32 to switch between sending and receiving data on the RS485 bus.
RS485 Communication Code for STM32
As previously mentioned, the goal is to establish communication between the two microcontrollers. The STM32F103 will initiate the communication by transmitting a message, and upon receiving this message, the STM32F446 will respond accordingly. This setup demonstrates a simple request-response mechanism using RS485.
The code for the F103
uint8_t TxData[16];
uint8_t RxData[16];
int indx = 0;
int main ()
{
HAL_UARTEx_ReceiveToIdle_IT(&huart1, RxData, 16);
while (1)
{
sprintf(TxData, "F103 %d", indx++);
sendData (TxData);
HAL_Delay(1000);
}
}
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
HAL_UARTEx_ReceiveToIdle_IT(&huart1, RxData, 16);
}
- Here in the main function we will first set the UART to receive the data.
- The function
ReceiveToIdle_IT
will receive the incoming data and store in the RxData buffer, until the Idle line is detected. - Once the RX pin is idle for some time, it will trigger the interrupt, which will eventually call the
RxEventCallbak
. - Inside this callback we will simply enable the receive to idle interrupt. This is because the HAL disables the interrupt after each call, so we need to enable it again after each time the interrupt is triggered.
- The function
- In the while loop we will update the string we want to send, with the incremented value of the indx variable.
- And we will keep sending this updated string every 1 second.
The sendData function used above is shown below
void sendData (uint8_t *data)
{
// Pull DE high to enable TX operation
HAL_GPIO_WritePin(TX_EN_GPIO_Port, TX_EN_Pin, GPIO_PIN_SET);
HAL_UART_Transmit(&huart1, data, strlen (data) , 1000);
// Pull RE Low to enable RX operation
HAL_GPIO_WritePin(TX_EN_GPIO_Port, TX_EN_Pin, GPIO_PIN_RESET);
}
- Before transmitting the data we need to put the RS485 module in the transmitter mode.
- To do this we have to pull the DE (Driver enable) pin as HIGH.
- Then we will send the data using the
HAL_UART_Transmit
Function. - Once the data is transmitted, we will enable the receiver mode by pulling the RE (Receive Enable) Pin LOW.
Remember that DE and RE are connected to the same pin (PA8, TX_EN), so we can use the same pin to set the module in transmitter or receiver mode.
Since the time of the incoming data is unknown, the module is always kept in the receive mode. Just before we want to send the data, we put it in the transmitter mode, and then put it back to receive mode again.
The transmitted data will be received by the F446 and it will send a response.
The code for the F446
Once the F446 receives the data, the RxEventCallback will be called, and we will write our code inside it.
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
RxData[0] = 'F';
RxData[1] = '4';
RxData[2] = '4';
RxData[3] = '6';
sendData(RxData);
HAL_UARTEx_ReceiveToIdle_IT(&huart1, RxData, 64);
// memset (RxData, '\0',64);
}
Here we will replace the first 4 bytes (‘F’ ‘1’ ‘0’ ‘3’) with the ‘F’ ‘4’ ‘4’ ‘6’ and send the data back to the first controller.
This is just a response and this way we would get an idea that the data is coming from the F446 itself.
The rest of the code is similar to that we saw for the F103.
Result for RS485 communication using STM32
Below are the images of the TxData and RxData buffers of the F103 controller.
As you can see the data transmitted and data received by the F103 are pretty much the same except the first few bytes.
So we transmitted “F103 46” from the F103 controller. This was received by the F446 and it changes the first few bytes and transmitted “F446 46” back to the F103 controller.
Conclusion
In this tutorial, we successfully interfaced an RS485 module with STM32 and demonstrated reliable half-duplex UART communication between two microcontrollers. By using the DE/RE control pin along with the HAL_UARTEx_ReceiveToIdle_IT()
function, we ensured smooth data transmission and reception without data loss.
RS485 communication is ideal for long-distance and multi-drop networks, making it widely used in industrial automation, Modbus communication, and sensor networks. Once you understand how to configure the UART peripheral, manage the TX enable pin, and handle the idle line interrupt, you can scale this setup to multiple devices on the same RS485 bus.
You can further enhance this project by implementing DMA for data transmission, adding error handling, or extending the code to support Modbus RTU protocol for real-world applications.
Browse STM32 Modbus Tutorials
Modbus #1. STM32 Master Reads Holding and Input Registers
Modbus #2. STM32 Master Reads Coils and inputs
Modbus #3. STM32 Master Writes single Coil and Holding Register
Modbus #3.1 STM32 Master Writes Multiple Coils and Registers
Modbus #4. STM32 as Slave || Read Holding and Input Registers
Modbus #5. STM32 as Slave || Read Coils and Inputs
Modbus #6. STM32 as Slave || Write Registers
STM32 RS485 Project Download
Info
You can help with the development by DONATING Below.
To download the project, click the DOWNLOAD button.
STM32 RS485 FAQs
Yes, you can connect multiple STM32 boards to a single RS485 bus because RS485 supports multi-drop communication. However, only one device should transmit at a time to avoid bus contention. You can implement a master–slave protocol like Modbus RTU to manage communication between multiple nodes.
Termination resistors are primarily needed for long cable lengths (typically above 10–15 meters) to prevent signal reflections. For short distances, you may not need them, but adding a 120 Ω resistor across A and B lines is still a good practice to ensure stable communication.
If the DE/RE pin is not controlled correctly, two issues can occur:
Early disable can cut off part of the transmitted data.
Late disable can keep the bus busy and block other nodes from transmitting.
Proper timing ensures that the transceiver switches between transmit and receive modes at the right moment.
Yes, RS485 works well with DMA. Using DMA for UART transmit and receive can free up the CPU and allow faster or continuous data transfers. You’ll still need to toggle the DE pin in the transmit complete callback to switch back to receive mode after DMA transmission ends.
You can use HAL status returns (e.g., HAL_OK
, HAL_TIMEOUT
, HAL_ERROR
) to detect transmission or reception errors. Additionally, enabling UART error interrupts can help catch framing errors, noise errors, or overrun errors. Proper error handling is crucial for robust RS485 communication in noisy environments.
Search This Site
Subscribe

Hello,
I am facing a issue that I could not receive proper data or continious data at both end.
Check for the baud rate. If the garbage data is received, it is because of the baud rate. Also make sure the clock configuration is correct as per your MCU.
I don’t understand what you mean continuous data is not being received.
Hi, I’m using STM32H750VB, I can’t find the instruction “HAL_UARTEx-ReceiveToIdle_IT()” in this family and I have error in my code.
Can I use “HAL_UART_Receive_IT()” instead of it??
It is available across all STM32 families. Make sure you have enabled the uart in the cubeMX. Also check if you are writing the function properly. It is not “HAL_UARTEx-ReceiveToIdle_IT()”, but “HAL_UARTEx_ReceiveToIdle_IT”