Description

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

7
Leave a Reply

avatar
4 Comment threads
3 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
5 Comment authors
DARINELMohitPhiladminSemachew Fasika Misrak Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
Semachew Fasika Misrak
Guest
Semachew Fasika Misrak

Can I use the code for EWARM(IAR IDE) as it is?

Phil
Guest

Hi, I’ve try it under ACR6 System workbench. With a few code modification, for include’s constants name or even struct for UART, it compile. But unfortunately the code end-up in an interrupt deadloop and the while(1) isn’t ran. I can trace it with the debugger, but I don’t have a clear idea of the typical path, so I can’t be sure of the part to fix. The code was ported to run on a STM32F0xx core. But I have a few STM32F1xx (Chinese bluepeal) on my hand too if you think it’s better for a first try. Would you please… Read more »

Mohit
Guest
Mohit

Do the above methods are applicable for any stm controller. Since I am using STM32 Nucleo F091RC and STM32 Nucleo L053R8 because transmitting is proper but receive methods are not working.
For nucleo do I need to do some hardware changes like shorting solder bridges etc?
Kindly help .your help will be valuable since i am stuck from past 3 days

DARINEL
Guest
DARINEL

Hi!!. Thanks for your time and effort.

Menu