蓝桥杯嵌入式物联网串口接收中断与空闲中断的最简实用方法

目录

文章目录

前言

一、串口的空闲中断?

二、使用步骤

1.打开串口中断(空闲中断加接受中断)

2.中断服务函数

总结

文章目录

  • 前言
  • 一、串口的空闲中断是什么?
  • 二、使用步骤
  • 1.引入库
  • 2.读入数据
  • 总结

  • 前言

    之所以写这篇文章,是因为参加蓝桥杯的时候发现HAL库的串口很难用,以至于串口总是接收都有问题。这篇文章还适合刚刚使用HAL库,回调函数用不习惯的同学,本文章以物联网L071为例来写,嵌入式G431也同样适用。

    一、串口的空闲中断?

    当使用串口接受数据的时候,你会发现不知道数据什么时间结束,网上也有一种方法教大家接受定长数据的教程,另一种方法就是在数据的后面加上结束位,这样就可以知道数据什么时间结束,从而去处理数据。这两种方法都有局限性,那什么样的方法更好呢?其实STM已经给了我们答案了,就是串口的空闲中断,这里先引用官方对串口空闲中断的解释:

    此位由检测到空闲线路时硬件设置。如果出现以下情况,则生成中断
    USART_CR1寄存器中的 IDLEIE=1。它由软件清除,将 1 写入 IDLECF
    USART_ICR寄存器。
    0:未检测到空闲线路
    1:检测到空闲线路
    注意:在设置 RXNE 位之前,不会再次设置空闲位(即新的空闲行)
    发生)。
    如果启用了静音模式 (MME=1),则在 USART 未静音 (RWU=0) 时设置空闲,
    无论唤醒位选择何种静音模式。如果 RWU=1,则不设置空闲。

    以上就是手册中对IDLE的解释,直白点来讲就是,当串口接受到数据后,它会自动检测后面还有没有数据,如果没有数据了,IDLE就置位,表示一帧数据接受完毕,它是在接受中断之后才置位的,如果没有接受的数据,空闲时它是不会置位的。

    二、使用步骤

    1.打开串口中断(空闲中断加接受中断)

    在CubeMX中只需要将串口模式设置为Asynchronous,其他不用动打开串口中断 就可以了。

     生成工程后在min()函数中添加打开串口中断的函数

    int main(void)
    {
      /* USER CODE BEGIN 1 */
    
      /* USER CODE END 1 */
    
      /* MCU Configuration--------------------------------------------------------*/
    
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      HAL_Init();
    
      /* USER CODE BEGIN Init */
    
      /* USER CODE END Init */
    
      /* Configure the system clock */
      SystemClock_Config();
    
      /* USER CODE BEGIN SysInit */
    
      /* USER CODE END SysInit */
    
      /* Initialize all configured peripherals */
      MX_GPIO_Init();
      MX_USART2_UART_Init();
      /* USER CODE BEGIN 2 */
    
      __HAL_UART_CLEAR_IDLEFLAG(&huart2);         //清除串口空闲中断
    	__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE);  //打开串口空闲中断
    	__HAL_UART_ENABLE_IT(&huart2,UART_IT_RXNE);  //打开串口接受中断
    
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
      }
      /* USER CODE END 3 */
    }
    

    一定要先清除串口空闲中断,然后在打开串口空闲中断,因为串口初始化完成后会自动将IDLE置位,导致还没有接受数据就进入到中断里面去了,所以打开IDLE之前,先把它清楚掉。 

    2.中断服务函数

    在中断服务函数中添加处理空闲中断的函数。

    void USART2_IRQHandler(void)
    {
      /* USER CODE BEGIN USART2_IRQn 0 */
    
      /* USER CODE END USART2_IRQn 0 */
    //  HAL_UART_IRQHandler(&huart2);
      /* USER CODE BEGIN USART2_IRQn 1 */
      if(__HAL_UART_GET_IT(&huart2,UART_IT_IDLE) !=RESET) {
    		ucTemp = 1;
    	__HAL_UART_CLEAR_IDLEFLAG(&huart2);
    	}
    	if(__HAL_UART_GET_IT(&huart2,UART_IT_RXNE) !=RESET) {
    		ucRxBuff[ucNum++] = USART2->RDR;
    	}
      /* USER CODE END USART2_IRQn 1 */
    }
    

    把串口中断函数中自动调用的函数注释掉,因为它每次调用完回调函数后都会关闭中断。(不使用回调函数,可以的提高串口接受的处理速度)当ucTemp置位时,代表数据接受完毕,然后清除空闲中断,下面是接受中断,接受中断不用清除。

    在while(1)中处理接收到的数据

      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
    		if(ucTemp == 1) {
    			ucTemp = 0;    //清除标志位
    			printf("%s\r\n",ucRxBuff);  //串口回显
    			memset(ucRxBuff,0,20);    //清除缓冲区
    			ucNum = 0;    //清除缓冲区指针
    		}
      }
      /* USER CODE END 3 */

    printf的重定向,同时keil中的USE Microlib打上勾

    int fputc(int ch,FILE*f)
    {
    	HAL_UART_Transmit(&huart2,(uint8_t *)&ch,1,10);
    	while(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_TXE) == RESET);
    	return ch;
    }


    总结

    如果有同学发现这样写还不能用,可以在串口初始化下面加上HAL_DELY(10),延迟一下,能用的同学可以略过,以上串口暂时在使用中没有发现什么问题,如果以上串口大家在使用中有什么问题,欢迎大家在下面留言,我们一起进步。

    作者:把握不住

    物联沃分享整理
    物联沃-IOTWORD物联网 » 蓝桥杯嵌入式物联网串口接收中断与空闲中断的最简实用方法

    发表回复