STM32串口第一次接收数据时第一个字节丢失的问题

发布于:2025-02-11 ⋅ 阅读:(60) ⋅ 点赞:(0)

解决方法:开启中断之前,先清除标志位【1】。

串口清除标志位:

__HAL_UART_CLEAR_PEFLAG(&huart1);

HAL_UART_Receive_IT(&huart1,&RxUart, 1);

定时器清除标志位:

__HAL_TIM_CLEAR_FLAG(&htim3,TIM_FLAG_UPDATE);

HAL_TIM_Base_Start_IT(&htim3);

1、问题描述

编程任务:STM32串口接收上位机不定长数组

思路:使用串口中断接收数据,每接收完一个字节就把计时器清零;计时器每65ms进一次中断,如果计时器进中断说明一帧数据结束了【2】。

1.1、MAIN函数

uint8_t RxData[60]={0},RxUart=0;
uint8_t FLAG_RX_DONE=0;//Serial port receive complete flag, no new data received within 65.5ms(TIM3), this flag will be set
uint8_t RX_DATA_idx=0,RX_DATA_LEN=0;


int main(void)
{
  uint8_t projectName[]="a1223_protocol";
  uint8_t i=0;

  printf("****** %s ******\r\n\r\n",projectName);

  HAL_UART_Receive_IT(&huart1,&RxUart, 1);//开启接受中断

  while (1)
  {
	  if(FLAG_RX_DONE!=0)//如果接收完成
	  {
		  FLAG_RX_DONE=0;

		  printf("RX_DATA_LEN=%d\r\n",RX_DATA_LEN);
		  RX_DATA_LEN=0;

		  printf("RX=");
		  for(i=0;i<RX_DATA_LEN;i++)
		  {
			  printf("%02X ",RxData[i]);
		  }
		  printf("\r\n");
		  
		  memset(RxData,0,sizeof(RxData));//清除接收寄存器
	  }

	  HAL_Delay(1000);
	  HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
}

1.2、串口接收中断处理程序

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)
	{
		__HAL_TIM_SET_COUNTER(&htim3,0);//定时器清零
		if(RX_DATA_idx==0)//If it is the first character, the timer is started
		{
			HAL_TIM_Base_Start_IT(&htim3);//开启定时器
		}

		RxData[RX_DATA_idx++]=RxUart;
		HAL_UART_Receive_IT(&huart1,&RxUart,1);//开启接收中断,准备接收下一个字节
	}
}

1.3、计时器中断处理程序

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance==TIM3)
	{
		//If no new data is received for 65.5ms, the reception is over
		RX_DATA_LEN=RX_DATA_idx;
		FLAG_RX_DONE=1;

		RX_DATA_idx=0;//Start writing data again
		HAL_TIM_Base_Stop_IT(&htim3);//接收完成,关闭定时器中断
	}
}

1.4、实验结果 

可以看到第一次接收的数据中缺少“01”。

2、解决方法

在开启中断之前,先清除标志位

2.1、串口的处理方法

HAL_UART_Receive_IT(&huart1,&RxUart, 1);

修改成

__HAL_UART_CLEAR_PEFLAG(&huart1);

HAL_UART_Receive_IT(&huart1,&RxUart, 1);

2.2、定时器的处理方法

 HAL_TIM_Base_Start_IT(&htim3);

修改成

__HAL_TIM_CLEAR_FLAG(&htim3,TIM_FLAG_UPDATE);

HAL_TIM_Base_Start_IT(&htim3);

 2.3、实验结果 

 

3、参考资料

【1】STM32串口第一字节消失或者误码的原因和解决方案_stm32单片机串口通讯 接收的字节错误-CSDN博客icon-default.png?t=O83Ahttps://blog.csdn.net/Backspace110/article/details/52737441

  【2】HAL库教程9:串口接收不定长数据_hal库接收串口不定长数据-CSDN博客icon-default.png?t=O83Ahttps://blog.csdn.net/geek_monkey/article/details/89326199