STM32的中断分为内核中断和外部中断,“内核中断”在《ARM CM3&CM4权威指南》中也被称作“系统异常”,如下所示:
今天主要讨论外部中断,即 CMSIS-Core中枚举值为正的异常(见表7.3)。
首先看关键词“中断线”,即“EXTI线”。STM32F407有23个外部中断,即23个中断线,从EXTI线0到EXTI线22。(此处书中似乎写成了22个中断线,貌似有误)
我们需要将I/O口与中断线之间建立映射关系,由于I/O口数量多于23,因此这种映射是多对一的,多个I/O口对应一个中断线。以EXTI线0为例,STM32按照GPIOA.0,GPIOB.0,GPIOC.0,GPIOD.0,GPIOE.0,GPIOF.0,GPIOG.0,GPIOH.0,GPIOI.0对应EXTI线0(即PA0,PB0,PC0,PD0,PE0,PF0,PG0,PH0,PI0均可以对应EXTI线0)。实际用到某个I/O引脚时,再通过配置决定具体哪个引脚对应EXTI线0。
接下来看关键词“步骤”,即配置外部中断的步骤。可以参考STM32的固件库函数stm32f4xx_exti.c代码和《精通STM32F4(库函数版)》。
代码中的注释部分可以看到:
##### How to use this driver #####
==================================================
[..] In order to use an I/O pin as an external interrupt source, follow steps
below:
(#) Configure the I/O in input mode using GPIO_Init()
(#) Select the input source pin for the EXTI line using SYSCFG_EXTILineConfig()
(#) Select the mode(interrupt, event) and configure the trigger
selection (Rising, falling or both) using EXTI_Init()
(#) Configure NVIC IRQ channel mapped to the EXTI line using NVIC_Init()
[..]
(@) SYSCFG APB clock must be enabled to get write access to SYSCFG_EXTICRx
registers using RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
书中的步骤也基本类似:
1.使能I/O口时钟,初始化I/O口为输入。—— GPIO_Init(),RCC_AHB1PeriphClockCmd
2.使能SYSCFG时钟,设置I/O口与中断线的映射关系。—— RCC_APB2PeriphClockCmd(),SYSCFG_EXTILineConfig()
3.初始化中断线(哪条EXTI线,中断模式是中断还是事件,触发方式是下降沿触发、上升沿触发还是任意电平触发,是否使能中断线)。—— EXTI_Init()
4.配置嵌套中断向量控制器NVIC。—— NVIC_Init()
5.编写中断服务函数。—— EXTI0_IRQHandler(),EXTI1_IRQHandler(),EXTI2_IRQHandler(),EXTI3_IRQHandler(),EXTI4_IRQHandler(),EXTI9_5_IRQHandler(),EXTI15_10_IRQHandler()。这些函数名称是在.s启动文件中定义的。
PS:这部分知识内容源自这位博主,大家感兴趣可以去这位博主这里了解,侵权请联系我删除。
https://blog.csdn.net/wofreeo/article/details/82725736
然后我们直接开始吧,这些理论的东西,自己去了解就好了。
准备工作:
1、STM32开发板(我的是STM32F407ZGT6)
2、STM32CubeMx软件、 IDE: Keil软件
3、STM32F1xx/STM32F4xxHAL库
4、按键管脚 PF9
5 LED管脚 PE3 PE4
RCC和SYS就不讲了,这个自己配就行了,很简单,如果不会看看我这篇文章
https://blog.csdn.net/weixin_53000184/article/details/124246194?spm=1001.2014.3001.5502
想了想还是给截图出来吧。
SYS:
RCC:
GPIO:
LED:2个GPIO_OUTPUT (输出模式)
按键:PF9按键GPIO_EXITx(外部中断模式)(按键为下降沿触发)
我使用PF9按键触发外部中断,配合两个LED观察现象。
GPIO output level 引脚电平设置 高/低
GPIO mode GPIO模式 推挽输出/开漏输出
GPIO Pull-up/Pull-dowm 上拉下拉电阻 上拉电阻/下拉电阻/无上拉或下拉
Maxinum output speed 引脚速度设置 低速/中速/高速
User Label 用户标签 给引脚设置名称 如LED0
主要是NVIC的配置。这里的EXIT的优先级一定要比Sys tick timer的低,我这里配2.(数字越小优先级越高)
时钟树的配置:
然后设置项目名称、选择储存路径、选择使用的IDE、生成工程。
在SMT32F4××_it.c中可以看到配置的中断服务函数,并且GPIO的初始化是在gpio.c里。
这里想要注意的是:在HAL库中,中断运行结束后不会立刻退出,而是会先进入相对应的中断回调函数,处理该函数中的代码之后,才会退出中断,所以在HAL库中我们一般将中断需要处理代码放在中断回调函数中。
我这里是把中断处理函数放在了stm32××_it.c文件的最底下。
注意:所有自己编写的代码请放在/* USER CODE BEGIN XXX */ /* USER CODE END XXX */之间,这样我们修改工程的时候你自己写的代码就不会被删除。
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(HAL_GPIO_ReadPin(GPIOF,GPIO_PIN_9)==GPIO_PIN_SET) {
HAL_Delay(30);
if(HAL_GPIO_ReadPin(GPIOF,GPIO_PIN_9)==GPIO_PIN_SET) {
HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_3);
HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_4);
while(HAL_GPIO_ReadPin(GPIOF,GPIO_PIN_9)==GPIO_PIN_SET);
}
}
}
别忘了设置debug。 我在main函数里,加了这两个操作,验证中断的执行效果。
大致现象就是:PE3和PE4这两个LED刚刚开始是亮着的,然后当我按下按键PF9,就会重复中断从而进入中断服务函数翻转PE3和PE4这两个LED的电平,(也就是不亮,这里面也有检测按键松手过程)。当中断处理完后,两个LED又会亮起。