[STM32]HAL library realizes DMA + serial port idle reception

I'm ashamed to say that I played single chip microcomputer for more than a year, but I haven't had a very good universal serial port receiving strategy. Before, my classmates recommended idle interrupt receiving. At that time, I didn't try it myself because of time. I remembered this thing when I was preparing to improve my basic code base in winter vacation.

Introduce the Idle interrupt of serial port. The reference manual says:

When an idle frame is detected, there is the same procedure as a data received character plus an interrupt if the IDLEIE bit is set.

This means that if IDLEIE is set, an interrupt will be triggered only after the idle frame after receiving data is detected

There are also many tutorials on configuring DMA + serial port idle on the Internet. I've seen a lot and feel it's very troublesome. I have to configure a lot of things myself. But out of habit, I often go directly to HAL library h file, so I found the following set of functions:

These are not only the three receiving functions of idle interrupt encapsulated by HAL library, but also the three receiving methods of blocking interrupt DMA.

These three functions were found on the Internet and almost no information was found, but fortunately, the annotations of HAL library are complete enough and can be read only by looking at the annotations.
Then our core function is this:
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
Here are its notes

/**
  * @brief Receive an amount of data in DMA mode till either the expected number of data is received or an IDLE event occurs.
  * @note   Reception is initiated by this function call. Further progress of reception is achieved thanks
  *         to DMA services, transferring automatically received data elements in user reception buffer and
  *         calling registered callbacks at half/end of reception. UART IDLE events are also used to consider
  *         reception phase as ended. In all cases, callback execution will indicate number of received data elements.
  * @note   When the UART parity is enabled (PCE = 1), the received data contain
  *         the parity bit (MSB position).
  * @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M = 01),
  *         the received data is handled as a set of uint16_t. In this case, Size must indicate the number
  *         of uint16_t available through pData.
  * @param huart UART handle.
  * @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
  * @param Size  Amount of data elements (uint8_t or uint16_t) to be received.
  * @retval HAL status
  */

It can also be seen from the comments that it will receive data through DMA, exceeding the length specified by us, or there is a serial port idle interrupt, which can be said to be in place in one step.
All we have to do is call this function, and then write a callback function to receive events.
This event callback function is also a break function that the HAL library helps us do in advance. You can define it in a place when you want to use it.
The following is the function call stack. You can see that the HAL library is still very complex

to configure

It's very simple. I'll do it myself. I don't want to write it in detail.
The main points are as follows:

  • Configure the serial port and DMA in CUBEMX, and then remember to open the interrupt of the serial port
  • Call function HAL_UARTEx_ReceiveToIdle_DMA
  • In callback function Hal_ UARTEx_ Record the data length received this time in rxeventcallback
  • If you want to receive data again, you must call the receiving function again

Added by ashishag67 on Thu, 27 Jan 2022 08:58:37 +0200