UART Interface


Since we need to develop a UI interface to control the STM32 and thereby control the sensor, we need to understand the STM32 UART transmission. However, I personally do not like using UART to control components because the transmission is not easy to write, and poor implementation can lead to issues such as data loss or causing the MCU to freeze. Therefore, in this case, the transmission length is known, and the receive length is also known, which allows us to write the UART transmission code accordingly. For reference, a section on receiving data with an unknown length will be provided below.


Setting steps

  1. Setting up UART in STM32CUBEMX involves enabling UART interrupts and enabling TX/RX DMA


Enable UART DMA channels

PS:that DMA is selected here to avoid data loss and program freezing caused by interrupts. If only IT interrupts are used, data loss may occur during reception when the program runs too quickly.

However, the drawback of DMA is that you must know the data length, otherwise, the next step cannot be executed smoothly. (Since both the UI and MCU coding are edited by me, the length is already known and there will be no exceptions.)

Different of Functin

使用輪詢-> HAL_UART_Transmit
使用中斷—> HAL_UART_Transmit_IT
使用DMA-> HAL_UART_Transmit_DMA
使用輪詢-> HAL_UART_Receive
使用中斷—> HAL_UART_Receive_IT
使用DMA-> HAL_UART_Receive_DMA
  1. Polling: It is a blocking inquiry in which the CPU does nothing but keeps asking, “Is there any data to be transmitted now?” If there is no data to be transmitted, the CPU continues to wait and keep asking. This method is the most primitive and inefficient, as it occupies too much CPU time.
  2. Interrupt:When no data is received, other programs are executed, and when data is received, it enters the interrupt processing communication. Compared with polling, there is no need to cyclically query the status register, so there is more time to run other programs
  3. DMA(Direct Memory Access):Direct access to memory. The transmission and reception of serial data are handled by DMA, which says, “I put the received/transmitted data in a certain location in memory, you can go there to extract it if you need it.” DMA can also be divided into polling and interrupt modes. Data transmission and reception do not require CPU intervention, but are carried out through DMA. The CPU has more time to run other programs.

Coding sample

Following the above steps in CubeMX, the declaration section will have these three additional lines.

UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart2_rx;
DMA_HandleTypeDef hdma_usart2_tx;


static void MX_DMA_Init(void);
static void MX_USART2_UART_Init(void);

The receive function used here is HAL_UARTEx_ReceiveToIdle_DMA(&huart2, &uRx_Data1, 14), mainly because HAL_UARTEx_ReceiveToIdle_DMA is a more advanced function that calls a callback when the data buffer is full or an idle character is received on the UART.

if( HAL_UARTEx_ReceiveToIdle_DMA(&huart2, &uRx_Data1,14) == HAL_OK)
		 if( uRx_Data1[0]=='a')
		 else if(uRx_Data1[0]=='b')
		 else if(uRx_Data1[0]=='c')
		 else if(uRx_Data1[0]=='d')
		 else if(uRx_Data1[0] >= '0' && uRx_Data1[0] <= '9')
		 else if(uRx_Data1[0]=='e')



Here, &uRx_Data1 is declared as unsigned char uRx_Data1[14] to receive the data. Since the incoming data is in ASCII format, not int, it needs to be converted to int, which can be done on either the UI side or within the STM32 MCU.

Since the data format for transmission is known to be x, x, xx…, with commas as separators and semicolon as the last character to confirm the end, and the first character identifies the mode, the received data is first checked to identify the mode.

String concatenation

Here, we use ‘,’ as the delimiter between each number and use ‘;’ as the last character to confirm the end. During the process, all received characters are numbers. It should be noted that since the incoming data is in ASCII format, we must subtract ‘0’ to convert it to an integer format.

For the output part, since the data can be received by the UI through the printf function in the following example, there is no additional code written here.

int _write(int file, char *ptr,int len)
	HAL_UART_Transmit(&huart2,(uint8_t *)ptr,len,1000);
	return len;

1 thought on “UART傳輸使用STM32 HAL實作TX/RX(STM32F401RE)”

  1. Pingback: LDM_Module_RPS800(TOF Measuring) - AMS and STM32

Leave a Comment

Your email address will not be published. Required fields are marked *

Shopping Cart