STM32F429之外部中断
7个中断通道在NVRC中使用
7个中断服务函数EXPORT EXTI9_5_IRQHandler
22个中断线
中断源为任意想要连接的GPIO,用那个连哪个SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
配置NVRC—配置GPIO(打开SYSCFG时钟)—连接中断源到GPIO—配置中断EXTI—编写中断服务函数
具体如下
STM32F4的每个IO都可以作为外部中断的中断输入口,这点也是STM32F4的强大之处。STM32F407的中断控制器支持22个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。STM32F407的22个外部中断为:
EXTI线0~15:对应外部IO口的输入中断。
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唤醒事件。
GPIO跟中断线的映射关系图:
库函数配置外部中断的步骤:
1) 使能IO口时钟,初始化IO口为输入
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(KEY1_INT_GPIO_CLK|KEY2_INT_GPIO_CLK ,ENABLE);
GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);
2) 开启SYSCFG时钟,设置IO口与中断线的映射关系。
/*使用GPIO外部中断时必须使能SYSCFG时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
配置GPIO与中断线的映射关系(连接中断源到GPIO引脚)
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
将中断线0与GPIOA映射起来,那么很显然是GPIOA.0与EXTI0中断线连接了。
3) 初始化线上中断,设置触发条件等。
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line=EXTI_Line4; (选择中断源)(EXTI_Line0~EXTI_Line15)
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; (中断模式)(分为中断和事件event)
EXTI_InitStructure.EXTI_Trigger= EXTI_Trigger_Falling;(下降沿触发)(上升沿触发Rising,任意电平触发Rising_Fallingr)
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure); //初始化外设EXTI寄存器
上面的例子设置中断线4上的中断为下降沿触发。4) 配置中断分组(NVIC),并使能中断。
设置中断线2的中断优先级。 在野火例程中,将NVRC设置成一个函数static void NVIC_Configuration(void) 在void EXTI_Key_Config(void)里调用。
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //使能按键外部中断通道中断线0-4每个中断线对应一个通道, 中断线5-9共用EXTI9_5_IRQ,中断线10-15共用EXTI15_10_IRQ
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //响应优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //中断优先级分组初始化
5) 编写中断服务函数。
EXPORT EXTI0_IRQHandler
EXPORT EXTI1_IRQHandler
EXPORT EXTI2_IRQHandler
EXPORT EXTI3_IRQHandler
EXPORT EXTI4_IRQHandler
EXPORT EXTI9_5_IRQHandler
EXPORT EXTI15_10_IRQHandler
中断线0-4每个中断线对应一个中断函数,中断线5-9共用中断函数EXTI9_5_IRQHandler,中断线10-15共用中断函数EXTI15_10_IRQHandler。
常用的中断服务函数格式为:
void EXTI3_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line3)!=RESET)//判断某个线上的中断是否发生
{ …中断逻辑…
EXTI_ClearITPendingBit(EXTI_Line3); //清除LINE上的中断标志位
}
}
总结一下使用IO口外部中断的一般步骤:1)使能IO口时钟,初始化IO口为输入。
2)使能SYSCFG时钟,设置IO口与中断线的映射关系。
3)初始化线上中断,设置触发条件等。
4)配置中断分组(NVIC),并使能中断。
5)编写中断服务函数。
简单例程如下
#include "stm32f4xx.h"
#include "stm32f4xx_exti.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_syscfg.h"
void main(void)
{
config();//初始化
while(1);
}
void config(void)
{
//中断IO口初始化
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); //
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
//GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOD, &GPIO_InitStructure);
//中断初始化
EXTI_InitTypeDef EXTI_InitStructure;
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource13);
EXTI_ClearITPendingBit(EXTI_Line13);
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
EXTI_InitStructure.EXTI_Line = EXTI_Line13;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
//中断配置初始化
/* Configures the nested vectored interrupt controller. */
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the USARTx Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//中断函数
void EXTI15_10_IRQHandler(void)
{
if( EXTI_GetITStatus(EXTI_Line13) != RESET )
{
EXTI_ClearITPendingBit(EXTI_Line13);//清中断
}
}