使用STM32hal库usart的接收中断分析及出现部分问题的解决

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37697335/article/details/81673053

最近开始使用ST的hal库,这个库相较于之前的标准库,优缺点兼具吧,hal库封装了更多底层的细节,我们可以很轻易的实现我们需要的功能,但是由于封装了太多的细节,导致一旦出问题,你就很难发现问题,内部调用的复杂让你觉得懵逼。

 

(一)hal库接收中断的分析

这几天在使用hal库的USART,其中用到的是接收中断,官方推荐的使用接收中断的方式是:在初始化函数上面先开启接收中断(这里就不介绍串口的配置,网上一大推,我就不给世界增加无谓的存储量了),开启的函数如下:

HAL_UART_Receive_IT(&huart2,(uint8_t*)aRxBuffer, 1);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量

接着直接调用总的回调函数就可以了(这个函数的名称是定义好的),的:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	

	if(huart->Instance==USART2)//判断,如果是串口2
    {

          //在这里写入自己要实现的代码
    }
	
}

其实使用回调函数的原理大概是这样的:MCU接收到数据产生中断,进入中断函数:

//串口中断服务程序
void USART1_IRQHandler(void)                	
{ 
	u32 timeout=0;	
	HAL_UART_IRQHandler(&UART1_Handler);	//调用HAL库中断处理公用函数
	
   //省略部分代码
   /*
   代码
  */
	}

也就是中断进入了HAL_UART_IRQHandler(&UART1_Handler);这个函数,这个函数是一个总的中断处理函数,也就是很多串口的中断处理最后都汇集到这个地方来处理。其实体如下:

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
   /*
    省略一部分代码
  */
      UART_Receive_IT(huart);
  /*
    省略一部分代码
   */
}

而UART_Receive_IT(huart);的实现如下:

static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
 /*
    省略一部分代码
   */
      HAL_UART_RxCpltCallback(huart);
 /*
    省略一部分代码
   */
}

也就是说最后会调用到  HAL_UART_RxCpltCallback(huart);,我们在这个函数内部做自己的需求就好了。

(二) 为了效率出了问题

由上面的分析,我们可以知道,hal库的中断接收虽然很方便,但是是非常没有效率的,兜兜转转绕了一个大弯才能处理中断接收的数据。尤其是我使用的是STM32F0的芯片,频率只有48M,不比那些动不动就上百兆的芯片,这样的中断处理显然不能接受。

所以,借鉴于标准库,我想直接在串口中断函数(void USART2_IRQHandler(void))上直接处理函数,而不用在转一个圈跑到回调函数( HAL_UART_RxCpltCallback(huart))上处理。

然而,一改,问题就来了,一共遇到过两个问题。

(1)一进中断就出不来

由于不知道之前hal库在中断处理做了什么手脚,所以自己也忘了判断和清除中断标志,加上下面几句话就好了。

void USART2_IRQHandler(void)
{
     /* UART in mode Receiver ---------------------------------------------------*/
    if((__HAL_UART_GET_IT(&huart2, UART_IT_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_RXNE) != RESET))
    {
			
      /*
      处理代码

      */

        /* Clear RXNE interrupt flag */ 
        __HAL_UART_SEND_REQ(&huart2, UART_RXDATA_FLUSH_REQUEST); //清除接收数据非空中断标志
    }	
}

(2)一进入中断MCU就死机

这个问题是由于我在中断处理了大量的任务导致的死机,虽然我之前同样在别的芯片上这样处理而没有出现问题,不过以前用的芯片比我现在用的这款强大太多了,还是那句老话:不要在中断干太多的任务。你可以在中断完成一些标志,或者处理一下接收的数据(可以转存到别的数据,但记住不要用hal库的函数,卡死不负责)然后在回到主函数处理。比如:


void USART2_IRQHandler(void)
{
     /* UART in mode Receiver ---------------------------------------------------*/
    if((__HAL_UART_GET_IT(&huart2, UART_IT_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_RXNE) != RESET))
    {
		flag_text=1;  //中断标志
        /* Clear RXNE interrupt flag */ 
        __HAL_UART_SEND_REQ(&huart2, UART_RXDATA_FLUSH_REQUEST); //清除接收数据非空中断标志
    }
}

最后,祝自己和各位少遇bug(不遇到是不存在的。。。)

猜你喜欢

转载自blog.csdn.net/m0_37697335/article/details/81673053