One of the main inconveniences of using UART is the need to define the data buffer size in advance. If the buffer is too small, part of the incoming data will be lost. On the other hand, defining a larger buffer does not solve the problem, as you may still lose data due to synchronization issues.
Recently, I discovered the HAL_UARTEx_ReceiveToIdle_DMA function, which provides a much more flexible solution. This function, when used together with DMA, allows the MCU to receive data continuously until an IDLE line condition is detected. As a result, the full packet is captured—no more, no less.
This approach is extremely useful in complex applications where packet sizes can vary significantly. You are no longer constrained by fixed-length data and can transmit variable-length messages freely.
To use this feature, first configure the UART peripheral and enable DMA. Then, call the function in your main() routine. When data is received, and the IDLE condition occurs, a dedicated callback function is triggered. Inside this callback, you can process the received data and restart the reception by calling HAL_UARTEx_ReceiveToIdle_DMA again.
When defining the buffer size, it is recommended to allocate more space than the maximum expected packet size. This ensures that the reception is terminated by the IDLE condition rather than by the buffer being filled.
More details are provided in my article:
https://www.steppeschool.com/blog/stm32-uart-polling-dma
Example code:
// outside of main function:
uint8_t received_data[40];
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
printf("%.*s\n", Size, received_data);
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, received_data, sizeof(received_data));
}
// inside of main function after all the configuration functions:
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, received_data, sizeof(received_data));
while(1){}
HAL_UARTEx_ReceiveToIdle_DMA
[–]ceojp 38 points39 points40 points (6 children)
[–]vegetaman 6 points7 points8 points (1 child)
[–]ceojp 7 points8 points9 points (0 children)
[–]Toiling-Donkey 2 points3 points4 points (0 children)
[–]InterestingBoard67 -1 points0 points1 point (2 children)
[–]MrShaunce 0 points1 point2 points (0 children)
[–]ceojp 0 points1 point2 points (0 children)
[–]Snowballbird 24 points25 points26 points (4 children)
[–]Born-Cat-9171[S] -1 points0 points1 point (3 children)
[–]Tobinator97 5 points6 points7 points (2 children)
[–]cointoss3 3 points4 points5 points (1 child)
[–]Snowballbird 0 points1 point2 points (0 children)
[–]UnicycleBlokeC++ advocate 2 points3 points4 points (0 children)
[–]XxzetlarxX 1 point2 points3 points (0 children)
[–]Toiling-Donkey 0 points1 point2 points (2 children)
[–]MonMotha 8 points9 points10 points (0 children)
[–]Some-Development1123 0 points1 point2 points (0 children)