lihui710884923
认证:VIP会员
所在专题目录 查看专题
嵌入式软件底层开发的框架
嵌入式串口通讯处理机制(附FIFO源码)
STM32 嵌入式平台上的语音识别系统
STM32F767ZI 之人工智能(AI) 应用
STM32 HAL库中断(绕来绕去)——剖析回调函数机制
stm32如何用虚拟地址存储数据
作者动态 更多
物联网专题之NB-IoT项目框架(二)
07-25 11:53
物联网专题之介绍(一)
07-11 18:37
单片机RTC的中断剖析
03-09 15:28
串口通讯的来龙去脉
02-14 17:32
stm32单片机的USB烧录程序
2023-09-08 22:48

STM32 HAL库中断(绕来绕去)——剖析回调函数机制

STM32Cube HAL出来六七年了,还是有很多初学者没有适应,今天就分享一个HAL库的关于中断处理的问题。

很多人都知道STM32CubeMX这套工具的一个目的:减少开发者对STM32底层驱动的开发时间,把重心放在应用代码上

但是,STM32CubeMX只是生成了底层驱动的初始化代码。所以,我们还需要掌握:应用层代码如何调用HAL库函数(API接口),以及HAL库中断处理机制等相关知识。

HAL库牵涉的内容较多,下面简单描述一下HAL库中断处理,以及相关的回调函数。

一、HAL库中断处理机制

之前使用标准外设库开发时,中断程序(函数)由我们自己实现。

而HAL库的中断处理函数是按照HAL处理机制来实现,如USART1,统一由HAL_UART_IRQHandler来进行处理,如下图:

其它大部分外设(TIM、SPI、CAN...)中断都类似,HAL进行统一处理。

也就是说,HAL已经帮我们把中断处理函数写好了,我们只需要调用相应函数来编写应用程序就行了。

HAL_xxx_IRQHandler里面做了哪些处理? 我们以STM32F1的HAL_UART_IRQHandler为例:

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
   uint32_t isrflags   = READ_REG(huart->Instance->SR);
   uint32_t cr1its     = READ_REG(huart->Instance->CR1);
   uint32_t cr3its     = READ_REG(huart->Instance->CR3);
   uint32_t errorflags = 0x00U;
   uint32_t dmarequest = 0x00U;

  /* If no error occurs */
  errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
  if(errorflags == RESET)
  {
    /* UART in mode Receiver -------------------------------------------------*/
    if(((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
    {
      UART_Receive_IT(huart);
      return;
    }
  }

  /* If some errors occur */
  if((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
  {
  /*
  ·
  ·删减了部分代码
  ·
  */
  } /* End if some error occurs */

  /* UART in mode Transmitter ------------------------------------------------*/
  if(((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
  {
    UART_Transmit_IT(huart);
    return;
  }
  /* UART in mode Transmitter end --------------------------------------------*/
  if(((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
  {
    UART_EndTransmit_IT(huart);
    return;
  }
}

其实,大家认真看一下代码应该能明白,这些和我们编写的中断处理函数是不是有类似之处?

这是无非就是接收中断、发送中断、错误中断等一系列处理。

只是这里又进行了再次封装,比如接收中断UART_Receive_IT。当然,这个UART_Receive_IT接收中断实现方式又可能存在不同。像F0、F1...就是直接调用这个接收中断函数来进一步处理。

像L0、G0...是通过执行指针函数RxISR来进一步处理。G0的接收中断处理为:huart->RxISR(huart);

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
  //删除了前面代码
  /* If no error occurs */
  errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE));
  if (errorflags == 0U)
  {
    /* UART in mode Receiver ---------------------------------------------------*/
    if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U)
        && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U)
            || ((cr3its & USART_CR3_RXFTIE) != 0U)))
    {
      if (huart->RxISR != NULL)
      {
        huart->RxISR(huart);
      }
      return;
    }
  }
  //删除了后面代码
}

看了上面USART中断处理的函数,大家有没有得到什么启发?

其实,HAL库里面处理机制基本一致,只是实现方式上有所不同

如果你摸清楚了HAL库基本原理,相信阅读HAL库源码,或者使用HAL库编写应用代码不是问题。

二、回调函数实现原理

在HAL库中存在大量类似HAL_XXX_XXXCallback这样的函数,这些都是回调函数

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

HAL库中断处理使用了较多的回调函数,还是拿UART接收中断来举例说明。

初始化配置好UART中断接收,如果有中断请求,就会执行回调函数HAL_UART_RxCpltCallback

看上面回调函数的定义,通过特定条件调用『回调函数』,这里触发的条件就是中断。

三、初学hal库建议

这里也简单说几点:

1.初学者想直接使用HAL不是不行,需要有一定C语言功底

针对大部分初学者来说,是不建议直接上手HAL。但是,有部分C功底较好的,还是建议直接上手。

2.学HAL,建议参看官网例程

很多人不知道如何找资源,我不止一次强调,官方的才是最好。在HAL库中Projects目录下就有很多例程Examples。

3.我们追求效率,可以HAL库源码

如果你想修改HAL库源码,允许修改少部分。如果要大量修改,还是别折腾了。

4.实际项目需做一定修改

STM32CubeMX仅仅是生成初始化代码和工程,你实际项目中一般都有自己的软件架构。

特别是项目越大,软件架构就需要更加规范。

比如:生成的gpio.c文件名,你需要修改成bsp_gpio.c.

再比如:函数MX_USART2_UART_Init改成MX_DEBUG_UART_Init.

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 10
收藏 11
关注 202
成为作者 赚取收益
全部留言
0/200
  • 小董 2021-03-25 12:40
    思路清晰,受益匪浅
    回复
  • dy-blNlwnWV 2021-02-24 23:08
    大开眼界,真是好文
    回复
  • keyhei66 2021-01-03 09:53
    精彩,很多东西还没接触到
    回复
  • 星球居民-YBPLIKJ1 2020-12-30 22:53
    不错
    回复
  • 米修儿 2020-12-29 17:53
    深度好文,学习了
    回复
  • 晨风 2020-12-28 15:46
    对我很有帮助
    回复
  • liuxiaofei126 2020-12-28 13:26
    围观学习
    回复