Receive UART data using POLL, INTERRUPT and DMA

As the title describes it, Today we will see 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

To transmit the Data using the UART, check out https://controllerstech.com/uart-transmit-in-stm32/

By using the POLLING

Let’s start with the simplest method 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 Reception is complete. This method is good to use if you are only using UART and nothing else, otherwise all other operations will be affected.

The Setup for this par is fairly Simple. We just have to enable the UART and that’s it.
Below the the picture of the Default setup in the CubeMX


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.

Here we can write instructions like “what to do after the Reception is complete?”.

In order to enable the Interrupt in CubeMX, we just need to modify our previous setup.

All we need to do is enable the interrupt in the Interrupt TAB under the UART. The Picture is shown below


To Receive data using the Interrupt, we will use

....
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.
  • 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.

To Setup the DMA, we have to ADD the DMA in the DMA Tab under the UART.

  • Here We are doing the Reception, so UART1_Rx DMA is added.
  • In the Circular mode, the DMA will keep Receiving the data.
  • After Receiving all the Required data, it will start automatically from the beginning.
  • Data Width is selected as Byte, as we are receiving characters, which takes only 1 byte in the memory.

To Receive the Data using the DMA, we will do as follows

....
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); 
}

int main ()
{
  ..........
  ..........

  HAL_UART_Receive_DMA (&huart2, Rx_data, 4);  // Receive 4 Bytes of data

  while (1)
  {
    HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_5);
    HAL_Delay (250);
  }
}
  • When the Half reception is complete, LED connected to A0 should toggle.
  • When all the data is received, RxCpltCallback will be called.
  • Here you can do the desired operation.
  • If you haven’t selected the Circular mode in DMA, you can start the DMA again.
  • If you have selected the circular mode, then no need to start the DMA, as it will start automatically.


Result

Check out the Video Below









Subscribe
Notify of
guest

8 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments

Adblocker detected! Please consider reading this notice.

We've detected that you are using AdBlock Plus or some other adblocking software which is preventing the page from fully loading.

We don't have any banner, Flash, animation, obnoxious sound, or popup ad. We do not implement these annoying types of ads!

We need money to operate the site, and almost all of it comes from our online advertising.

Please add controllerstech.com to your ad blocking whitelist or disable your adblocking software.

×