空闲中断+接收中断实现串口数据的不定长接收 ---- 基于STM32 hal库

  • A happy life isn’t hard to come by, the trick is to not regret the choices you made along the way.
    平安喜乐的日子不难有,关键在于不要为你做出的任何选择而感到后悔。

一、需求及实现思路

  • 需求
    我们经常遇到这样的场景:由于不确定对方通过串口发过来的数据有多长,我们就不好对这些不定长的数据进行处理,所以我们需要实现这个方式的策略。
  • 策略
    很多单片机(包括STM32)就提供了策略来因对这种需求,也就是利用空闲中断。思路是这样的:
    我们开启单片机的接收中断和空闲中断,在单片机接收据时,会触发中断,判断如果是接收中断,接收数据,并对数据进行计数。如果是由于一段时间没有数据造成的空闲中断,则表明数据完成接收,标记数据接收完成。
    然后在别的地方判断数据接收完成标志是否达成,若达成,则处理数据。

二、环境

  • 开发软件:MDK5、STM32CubeMx
  • 开发板:STM32F407、STMF042
  • USB转TTL模块

三、实现(以裸机为例)

  • 2.1、STM32CubeMX配置好串口,开启中断。(网上资料很多,不赘述)
  • 2.2、定义一个用于接收数据的结构体:
#define RX_BUF_MAX_LEN     1024        // 最大接收缓存字节数
struct  USARTx_Fram                    // 串口数据帧的处理结构体
{
	char  Data_RX_BUF[RX_BUF_MAX_LEN]; // 数据缓冲区
	int FramLength; // 数据长度
    FramFinishFlag; // 接收完成标记
} ;

struct  USARTx_Fram  USART3_Fram_Record = {0};
  • 2.3、在主循环前打开接收中断和空闲中断:

      HAL_UART_Receive_IT(&huart3,&RxBuffer,1); // 使能接收中断
      /*Enable the IDLE Interrupt*/
      __HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE); // 使能空闲中断
      while (1)
      {
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
      }
    
  • 2.4、在中断中根据中断类型处理数据(改写STM32CubeMX生成的中断函数)

    void USART3_IRQHandler(void)
    {
        if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_RXNE) != RESET)
        {
             HAL_UART_IRQHandler(&huart3); // 该函数会清空中断标志,取消中断使能,并间接调用回调函数,清除接收标志
    
            // 收到数据,将其放入缓冲区
            if(USART3_Fram_Record.FramLength < RX_BUF_MAX_LEN)  
                USART3_Fram_Record.Data_RX_BUF[USART3_Fram_Record.FramLength++] = RxBuffer;
        }
        
        if(__HAL_UART_GET_FLAG(&huart3, UART_FLAG_IDLE) != RESET)
        {
            __HAL_UART_CLEAR_IDLEFLAG(&huart3);     //清楚空闲中断标志(否则会一直不断进入中断)
    
            USART3_Fram_Record.FramFinishFlag = 1;  // 标记接收完成 
        }
        
        HAL_UART_Receive_IT(&huart3,&RxBuffer,1);   // 重新使能接收中断 
    }
    
  • 在主循环中判断是否完成即可处理数据,举例如下:

    while(1)
    {
    	..................
    	if(1 == USART3_Fram_Record.FramFinishFlag)
    	{
    		// 处理数据的代码
    		USART3_Fram_Record.FramFinishFlag = 0;
    		USART3_Fram_Record.FramLength = 0;
    	}
    	.....................
    }
    

你可能感兴趣的:(STM32,笔记)