How to receive UART data in STM32
As the title describes it, Today I am writing about how to Receive UART (SERIAL) data using POLL INTERRUPT and DMA. I am going to use all three methods and show you the difference between all three. There is a video attached at the end of this post. Do check it to see the working.
I will use all three methods to Receive serial data here i.e
- using the poll —> HAL_UART_Receive
- using the interrupt —> HAL_UART_Receive_IT
- and using DMA —> HAL_UART_Receive_DMA
using the POLL method
Starting with the simplest one i.e using the POLL method. The data is Received in blocking mode i.e the CPU will block every other operation until the data transfer is complete. This method is good to use if you are only using UART and nothing else otherwise all other operations will be affected.
To Receive data using POLL method, simply use
uint8_t Rx_data[10]; // creating a buffer of 10 bytes
while (1)
{
HAL_UART_Receive (&huart2, Rx_data, 4, 100); // receive 4 bytes of data
HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_5); // toggle LED
HAL_Delay (250);
}
I am using toggle LED for you guys to better understand what happens when we try Receiving data. This is best explained in the video, Please check it out. Also ‘100’ is the timeout for the UART Rx here.
You will notice that even after sending 4 bytes of data, UART only receives 1 byte. This is because the reception timed out after 100 ms. That’s why only 1 byte of data is received. So what should we do if we want to receive all 4 bytes ?
Well we will increase the timeout. Now let’s set to 1 sec and see what happens.
uint8_t Rx_data[10]; // creating a buffer of 10 bytes
while (1)
{
HAL_UART_Receive (&huart2, Rx_data, 4, 1000); // receive 4 bytes of data
HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_5); // toggle LED
HAL_Delay (250);
}
As I already mentioned above that in POLL method, data is processed in blocking mode. So all other executions are blocked until the data is received or the timeout happens. That’s why the LED blink rate reduces here. To overcome this, we will use INTERRUPT or DMA methods.
using the INTERRUPT
In interrupt mode, Reception takes place in non-blocking mode or in the background. So the rest of the processes works as they should and when the data Reception is complete, a Rx Complete Callback is called where we can write instructions like “what to do after the Reception is complete?”.
uint8_t Rx_data[10]; // creating a buffer of 10 bytes
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_Receive_IT(&huart2, Rx_data, 4);
}
HAL_UART_Receive_IT (&huart2, Rx_data, 4);
while (1)
{
HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_5);
HAL_Delay (250);
}
In the above code, HAL_UART_RxCpltCallback will be called when the data reception is complete and as you can see inside this function, I am again starting a new data reception. This will result in continuous reception of data and the rate of blinking will also remain constant as the data transfer takes place in non-blocking mode or in the background.
Note that if you do not start the reception again (inside HAL_UART_RxCpltCallback function), the reception will only take place once.
using the DMA
DMA also works somewhat same as interrupt, means that data transfer is in a non-blocking mode.
In DMA, when half the data gets Received, a HALF Received COMPLETE INTERRUPT gets triggered and HAL_UART_RxHalfCpltCallback is called and when the data transfer completes, HAL_UART_RxCpltCallback is called.
uint8_t Rx_data[10]; // creating a buffer of 10 bytes
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
{
HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_0); // toggle PA0
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_Receive_DMA(&huart2, Rx_data, 4);
}
HAL_UART_Receive_DMA (&huart2, Rx_data, 4);
while (1)
{
HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_5);
HAL_Delay (250);
}
As you can see above that When the Half reception is complete, LED connected to A0 should toggle and it does.
You can see that in the video attached below
How to receive UART data in STM32
Reviewed by Controllerstech
on
July 21, 2018
Rating:
excellent
ReplyDeleteThanks for the perfect explanation! I've read so many topics on this, and still didn't understand how I was supposed to implement a simple UART protocol on STM.... But this really hammers it down! Thanks a bunch!!
ReplyDeleteVery nice and brief explanation
ReplyDeleteCan I use this approach of Interrupt for Gps and Gsm communication. How to do that exactly using HAL.
ReplyDeleteHello..i liked the explanation. For me, i am using stm32f103c8 and programming it with STLink V2. So the com port doesnt show for STLink and hence i am unable to use the hercules utility tool or any other tools. I have tk recieve data on Stm32f103c8 from NodeMCU..could u help me with this..
ReplyDeleteI follow your code, The Pooling UART, Interrupt UART work, but HAL_UART_Receive_DMA did not work. Do you know why?
ReplyDeletenapim
Deleteama sen aglion
DeleteIn ISR & DMA mode, what if data to be received is variable and not fixed?
ReplyDelete