2022年10月10日 星期一

[STM32] How to use UART to receive data of variable length

There are many cases where data of unknown length is received via UART, such as in Modbus and AT commands. However, HAL functions do not provide a direct method for this. Here is a simple example that utilizes the UART IDLE interrupt to achieve this.

First, define the relevant variables in main.c:


uint8_t RxBuffer[1024];
uint8_t UartReady;
uint8_t RxCount;

Define the variables before the while(1) loop, enable the IDLE interrupt function, and use UART receive interrupt:


__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE);
HAL_UART_Receive_IT(&huart2, (uint8_t *)RxBuffer, 1024);

Since we are using UART interrupts, we need to modify the IRQHandler function:

Since we are relying on UartReady to detect incoming data, we need to create a separate loop to process the received data. In this loop, we can parse the received data and pass it to the backend program for further processing. We can also calculate the length of the data received during this loop and store it in the RxCount variable.



extern uint8_t UartReady;
extern uint8_t RxCount;

void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */

 if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE) != RESET)
 {
  RxCount = 1024 - huart2.RxXferCount;
  __HAL_UART_CLEAR_IDLEFLAG(&huart2);
  HAL_UART_AbortReceive_IT(&huart2);

  UartReady = SET;
 }
  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */

  /* USER CODE END USART2_IRQn 1 */
}


while(1)
{
 if(UartReady == SET)
 {
  //RxBuffer do something.....
  
  UartReady = RESET;
  HAL_UART_Receive_IT(&huart2, (uint8_t *)RxBuffer, 1024);  
 }
 HAL_Delay(100);
}