HAL库:中断处理函数 及 weak弱声明中断回调函数 详解

此文已重新修整,请跳转这里来查看

超子物联网 HAL库学习 汇总入口:

超子物联网HAL库笔记:[汇总]

HAL库:中断处理函数 及 weak弱声明中断回调函数

一、STM32 中断处理方式概述

在 STM32 的开发中,中断是一种非常重要的机制,用于响应外部事件或内部异常情况。STM32 在启动文件(stmxxxxx.s)中为我们预先定义了所有中断的中断服务函数。这意味着当特定的中断发生时,处理器会自动跳转到相应的中断服务函数处执行代码。

二、标准库中断处理方式

在标准库中,处理中断需要开发者自己去判断中断标志位,确定中断是否发生,然后执行相应的操作,最后还需要手动清除中断标志位。例如在 EXTI15_10_IRQHandler 中断服务函数中,开发者需要通过检查特定的线(比如线 12)的中断标志位来判断该中断是否发生,如果中断标志位为真,则执行特定的操作,最后还需要清除线 12 产生的中断标志位,以确保下次中断能够正确响应。

三、HAL 库中断处理方式

  1. 自动判断与清除标志位
    • HAL 库(以 gpio.c 为例)为各个外设的中断提供了更加便捷的处理方式。在 HAL 库提供的中断处理函数中,会自动判断中断标志位并清除标志位。例如在 void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)函数中,首先使用__HAL_GPIO_EXTI_GET_IT(GPIO_Pin)!= 0x00u来判断标志位,确定中断是否发生。如果中断发生,接着使用__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin)来清除标志位,确保下次中断能够正常响应。
  2. 回调函数机制
    • 在自动判断和清除标志位的函数中,还提供了一个回调函数HAL_GPIO_EXTI_Callback(GPIO_Pin)。这个回调函数的作用是在中断发生并且标志位被正确处理后,执行用户自定义的操作。
  3. 弱声明的回调函数
    • 在自动判断和清除标志位的函数下,会有回调函数有一个弱声明:__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)。这个弱声明的回调函数只是为了防止编译报错而存在的,它内部实际上什么操作都不执行,只是通过UNUSED(GPIO_Pin)来告诉编译器这个参数虽然没有被使用,防止产生编译错误。
  4. 强声明的回调函数
    • 开发者可以在自己的代码中定义一个 “强声明” 的中断回调函数,即void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)。当程序编译时,会自动使用这个强声明的回调函数替代弱声明的回调函数。这样,当中断发生时,就会执行开发者自定义的回调函数,而不是弱声明的空函数。

gpio.c中判断中断、清除中断、执行回调函数和对应的弱声明的代码部分:

//stm启动文件中已经定义的中断服务函数
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
  if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)//帮我们判断标志位
  {
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);//帮我们清除标志位
    HAL_GPIO_EXTI_Callback(GPIO_Pin);//执行回调函数
  }
}

// 弱声明 的回调函数  只是为了防止报错用
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  UNUSED(GPIO_Pin);//什么都不执行,只是为了防止编译时报错:没有使用xxx
}

四、在程序中的应用

为了让 HAL 库的中断处理函数能够正确地响应中断并执行自定义的回调函数,我们只需要在 it.c 文件中,在中断发生时跳转到 HAL 库的中断处理函数。这样,当中断发生时,HAL 库的中断处理函数就会自动帮我们判断中断标志位、清除标志位,并进入对应的回调函数,执行我们自定义的操作。

比如(以gpio.c为例):

it.c文件:

void EXTI15_10_IRQHandler (void) //如果发生了这个中断
{
	HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);//跳转到HAL库的中断处理
	HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);//跳转到HAL库的中断处理
} 

xx.c文件(其他文件):

/* 注册回调函数 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == GPIO_PIN_13) // 判断是不是13线
    {
        // 执行13线程序
        // ...
    }
    else if (GPIO_Pin == GPIO_PIN_12) // 判断是不是12线
    {
        // 执行12线程序
        // ...
    }
}

### HAL 中断回调函数定义与实现位置 在STM32Cube HAL中,中断回调函数的设计允许开发者自定义特定事件发生时的行为。这些回调函数通常用于处理各种硬件外设产生的中断请求。 #### 中断回调函数的注册和调用机制 当配置好相应的外设并使能其中断后,实际发生的中断会触发进入对应的中断服务程序(ISR),ISR内部则负责调用预定义好的回调接口。对于UART串口中断而言,其接收完成后的处理逻辑即封装在一个名为`HAL_UART_RxCpltCallback()`的方法内[^1]: ```c void USARTx_IRQHandler(void) { /* Enter interrupt service routine */ HAL_UART_IRQHandler(&huart); } /* UART error callback function */ void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) { // Customized handling code here... } ``` 上述代码片段展示了USART中断处理器如何通过调用`HAL_UART_IRQHandler()`来响应UART设备上的活动,并最终可能执行到错误情况下的回调方法。 #### 用户定制化部分 为了方便用户扩展功能而不必修改底层驱动源码,HAL提供了多个默认为空操作(`__weak`)声明符号版本回调入口点。这意味着如果应用程序未提供具体实现,则编译链接阶段会选择内置的标准行为;反之若有重载,则优先采用应用层给出的新版定义[^2]。 例如,在初始化项目时生成的基础框架文件里已经包含了如下形式的模板声明: ```c /** * @brief This function handles UART communication errors. * @param huart Pointer to a UART_HandleTypeDef structure that contains the configuration information for the specified UART module. * @retval None */ void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) { /* Prevent unused argument(s) compilation warning */ UNUSED(huart); /* NOTE : This function should not be modified, when the callback is needed, the HAL_UART_ErrorCallback can be implemented in the user file. */ } ``` 这段说明告知开发人员可以在自己的源文件中重新定义此函数以适应项目的特殊需求。 #### 查找具体的定义或实现位置 要定位某个特定于某类外设(如UART、TIM等)的中断回调函数的确切路径,可以从以下几个方面入手: - **stm32xx_hal_msp.c**: 这个文件通常位于工程目录下,包含一些多态性的初始化/去初始化钩子函数以及某些情况下也会有简单的回调示例。 - **stm32xx_it.c**: 此处集中管理着所有由工具链自动创建出来的裸机级中断向量表项及其关联的服务程序,虽然这里主要是ISRs而非真正的业务逻辑所在,但是了解它们有助于追踪后续流程走向。 - **main.c 或其他业务逻辑模块**: 开发者往往会在主要的应用场景描述单元(main loop之外的地方)放置那些真正想要被执行的任务——也就是对各个组件状态变化作出反应的具体措施,这正是编写个性化回调的好地方。 综上所述,针对不同的应用场景和个人偏好,可以选择合适的位置来安置所需的中断回调函数实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

L_Z_J_I

让孩子吃一顿免费的午餐吧!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值