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/
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
- 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.
- 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.
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
- In the above code,
HAL_UART_RxCpltCallbackwill 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.
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
- 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.