目录
外部中断/事件控制框图
在下面的外部中断/事件控制框图中,可以看到输入线到NVIC的过程,如图中的1线。
1)外部信号由输入线进入进入边沿检测电路(需要设设置上升沿触发选择寄存器或者选择下降沿触发选择寄存器,图中的2线,3线)
2) 软件中断事件寄存器,这个寄存器与边沿检测电路共同经过一个"或门",也就是既可以通过外面的电路输入触发信号,也可通过软件设置该寄存器,中断的输入的。图中的4线
3)中断屏蔽寄存器,这个寄存器与1线经过一个“与门”,这个寄存器就是我们经常说的中断使用寄存器,通过对其设置使能或屏蔽中断。
4)挂起请求寄存器,其实是中断请求标志位,中断产生时会在该寄存器中有标志位。
23根外部中断线
STM32F407可以支持23个外部中断请求,也就是有23根外部中断输入线,但是为了更合理的利用资源,STM32F407并不是直接提供23个中断引脚。而是通过引脚复用的方式实现资源的合理化,所有的GPIO0 连接到外部中断线0上(EXTI0)。以此类推一个GPIO分组上有16个PIN脚因此占EXTI线(0-15)。
注:由于相同引脚号的引脚连接到对应的EXTI线上,也就是说只有其中的一直引脚能设置为对应外部中断,例如(PA0---PI0)中,只有其中一直引脚能够设置为外部中断0。不能够PA0设置外部中断0后,又设置其他引脚为外部中断0
另外七根 EXTI 线连接方式如下:
● EXTI 线 16 连接到 PVD 输出
● EXTI 线 17 连接到 RTC 闹钟事件
● EXTI 线 18 连接到 USB OTG FS 唤醒事件
● EXTI 线 19 连接到以太网唤醒事件
● EXTI 线 20 连接到 USB OTG HS(在 FS 中配置)唤醒事件
● EXTI 线 21 连接到 RTC 入侵和时间戳事件
● EXTI 线 22 连接到 RTC 唤醒事件
STM32CubeMx配置外部中断
注:外部中断需要设置优先级>0,因为HAL_Delay使用到systick定时器中断(Time base :system tick timer),否则systick无法抢占外部中断,陷入死循环。
HAL库中外部中断初始化
外部中断的初始化,MX_GPIO_Init函数中,设置引脚号,下降沿触发,上拉。
通过HAL_NVIC_SetPriority(EXTI15_10_IRQn, 1, 0),设置优先级,
通过HAL_NVIC_EnableIRQ(EXTI15_10_IRQn),设置开启中断
注:
1)在函数HAL_NVIC_SetPriority(EXTI15_10_IRQn, 1, 0),1代表抢先优先级,0代表次优先级。数字越低,优先级越高;
2)抢占优先级的意思是抢占优先级高可以抢占其他中断抢占优先级低的中断;
3)次优先级则是如果抢占优先级相同,同时发生中断时,哪个次优先级高则先执行哪个中断。
4)抢占优先级相同,如果次优先低的中断先执行,次优先级高的需要等待次优先级低的外部中断执行完,才能执行次优先级高的外部中断。
HAL库中实现函数中断服务过程
从上一章可以知道,中断向量表中会有对应的中断服务函数地址,如果有中断触发,将会去中断向量表中,寻找中断服务函数的地址,跳转到中断服务函数。我们使用的PB12引脚,对应的中断服务函数为void EXTI15_10_IRQHandler(void)。
中断服务函数调用了 HAL_GPIO_EXTI_IRQHandler函数,该函数检查中断标志位,并清除中断标志位后,调用void HAL_GPIO_EXTI_Callback函数
在HAL中,并不知道到用户想实现怎样的中断功能,因此调用默认的__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) 弱函数。
注: “__waek” ,是STM32拓展的标识符,将函数定义为弱函数,里面没有实现的功能用来占位置,防止编译出错。
因为默认调用为弱函数,因此需要自定义中断回调函数,代替默认的弱函数。
注:在所有的外部函数都会调用HAL_GPIO_EXTI_Callback函数,因此需要在回调函数中判断是哪一只引脚引起的中断。本例子中使用PB12。