加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
    • 1、HAL 库中断处理机制
    • 2、回调函数实现原理
    • 3、扩展说明,这里也简单说几点:
  • 推荐器件
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

STM32Cube HAL库中断处理机制,回调函数实现原理

2020/12/29
554
阅读需 11 分钟
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

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

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

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

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

1、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 库编写应用代码不是问题。

2、回调函数实现原理

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

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。

回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

--- 来自百度百科

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

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

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

3、扩展说明,这里也简单说几点:

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.

关注微信公众号『嵌入式专栏』,底部菜单查看更多内容,回复“加群”按规则加入技术交流群。

推荐器件

更多器件
器件型号 数量 器件厂商 器件描述 数据手册 ECAD模型 风险等级 参考价格 更多信息
M24C02-WMN6TP 1 STMicroelectronics 2 Kbit serial I<sup>2</sup>C bus EEPROM

ECAD模型

下载ECAD模型
$0.17 查看
KSZ9567STXI 1 Microchip Technology Inc IC ETHERNET SWITCH 7PORT 128TQFP

ECAD模型

下载ECAD模型
$15.29 查看
TLP291-4(V4GBTPE(T 1 Toshiba America Electronic Components Transistor Output Optocoupler, 4-Element, 2500V Isolation
$2.08 查看

相关推荐

电子产业图谱

作者黄工,从事嵌入式软件开发工作8年有余,高级嵌入式软件工程师,业余维护公众号『strongerHuang』,分享嵌入式软硬件、单片机、物联网等内容。