野火STM32_HAL库版课程笔记-外部中断应用与回调函数
外部中断
芯片外部的 GPIO 输入中断, 通过检测 GPIO 的输入变化, 来产生中断或者是事件请求的外设模块.
EXTI 简介
EXTI(External interrupt/event controller)—外部中断/事件控制器,管理了控制器的20 个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。EXTI 可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。
中断/事件线

中断优先级

抢占优先级:决定了一个中断能否打断正在执行的其他中断(即“插队”)
响应优先级:当多个中断的抢占优先级相同时,决定了它们的执行顺序(即“排队”)
两者都是数值越小, 优先级越高. (先看抢占优先级, 再看响应优先级)
主要区别是: 抢占优先级高可以打断其他中断, 而响应优先级高并不能打断其他中断.
上面的表格主要就是说明有 5 种优先级的分组方式
不同的分组方式, 其抢占优先级与响应优先级能够设置的级别不同.
(设置抢占级别多, 响应能设置的级别就少了, 反之亦然)
外部中断/事件控制器框图

图中的 20 , 表示 20 个中断/事件线
输入线就是中断的输入信号进入,
经过边沿检测电路(设置的 "上升沿" or "下降沿" 触发)
然后经过 ③ 或门, 该或门的两个来源分别为: 软件中断事件寄存器, GPIO 引脚边沿检测.
然后继续向左, 通过请求挂起寄存器.
请求挂起寄存器用来记录某个中断事件已经发生, 但还没被处理的标志寄存器.
(告诉 CPU 这里产生了一个中断, 需要处理, 就会在对应的寄存器中对应位写 1, 表示中断挂起了, 等待 CPU 处理.
当 CPU 知道之后就会手动清除这个挂起位, 表示该中断已经在处理, 可以将该标志清除. 否则会一直挂起, CPU 也会一直处理)
再向做, 经过 ⑥ 与门 (两个输入都有效, 才会输出), 当已经成功挂起, 并且通过一个事件屏蔽寄存器(控制是否允许某条中断线/事件线产生中断或事件, 即 允不允许中断产生, 如果允许, 在寄存器中通常设置为 1).
然后在经过 ⑦ 脉冲发生器来触发事件.
而当配置的是触发中断, 则经过的是 ④ 与门, 同样经过挂起寄存器已经挂起 并且中断屏蔽寄存器允许产生中断, 两个信号有效. 经过与门产生信号至 NVIC 中断控制器中, 产生中断.
回调函数应用
回调函数的作用 —— HAL_GPIO_EXTI_Callback ()
回调函数是什么?
回调函数是用户定义的函数,由库函数在特定事件发生时自动调用。
HAL_GPIO_EXTI_Callback() 是 HAL库提供的 GPIO 外部中断回调函数。
为什么要用回调函数?
把中断触发和业务逻辑分开,结构更清晰。
多个引脚共用一个回调函数,方便集中管理多个中断来源

项目配置
GPIO 配置

使用核心板上 KEY1 作为外部中断输入, 其对应引脚为 PA0
设置 PA1, PA2, PA3 对应核心板上三个 LED 灯, 默认电平为高 (灯灭)
设置 PA0 为 GPIO_EXTI0, GPIO mode 为 External Interrupt Rising edge trigger detection(外部中断上升沿 (低电平变高电平) 触发检测)

NVIC 配置
首先, 使能 EXTI0l, 点击右侧复选框勾选即可.
![]()
设置优先级分组

这里选择第四个优先级分组, 因为现在只用到这一个中断, 也用不到响应优先级. 所以随意, 其他选项默认

代码部分

这个函数在 EXTI0_IRQHandler -> HAL_GPIO_EXTI_IRQHandler 中被调用

这里 HAL_GPIO_EXTI_IRQHandler 对应的是检测我们指定引脚的中断挂起标志是否被设置.
也就是表示该引脚确实触发了中断, 就会调用这个 HAL_GPIO_EXTI_Callback 回调函数. (并且清除标志)
HAL_GPIO_EXTI_Callback
这里的 HAL_GPIO_EXTI_Callback 是一个 弱定义 函数, 该函数是用户自定义的.
以方便我们在别的地方编写一个函数来覆盖它.
该函数的参数也是 GPIO_Pin, 也就是引脚, 那么我们就可以在这个函数里判断传入的引脚是哪一个引脚.
通过区分引脚来做出对应的中断反应.
这里的 UNUSED(GPIO_Pin); 是如果在函数中没有用到参数, 编译器会有警告 (参数没有被使用) .
使用这个函数就可以消除编译器的这个警告.
当我们在其他地方编写好这个函数之后, 当外部中断触发时, 就会自动调用该回调函数, 来执行对应的代码.

在 USER CODE BEGIN 4 处定义这个函数. 并编写业务逻辑代码 (外部中断触发按键亮灭灯)
/* USER CODE BEGIN 4 */
/**
* @brief EXTI line detection callbacks.
* @param GPIO_Pin: Specifies the pins connected EXTI line
* @retval None
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == KEY1_EXTI0_Pin) // 触发外部中断的是对应的 KEY1 的引脚 | 中断来源是按键1
{
// 切换红, 绿, 蓝三个LED灯的状态 (灭->亮, 亮->灭)
HAL_GPIO_TogglePin(GPIOA, LED_R_Pin | LED_G_Pin | LED_B_Pin);
}
}
/* USER CODE END 4 */
更多推荐



所有评论(0)