https://blog.csdn.net/liu112125/article/details/115870551
1… 外部中断概述:
STM32 的每个 IO 都可以作为外部中断的中断输入口,这点也是 STM32 的强大之处。STM32F103 的中断控制器支持 19 个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。
STM32F103的 19 个外部中断为:
线 0~15:对应外部 IO 口的输入中断。
线 16:连接到 PVD 输出。
线 17:连接到 RTC 闹钟事件。
线 18:连接到 USB 唤醒事件。
STM32 供 IO 口使用的中断线只有 16 个,但是 STM32 的 IO 口却远远不止 16 个,但是GPIO 的管脚GPIOx.0~ GPIOx.15(x=A,B,C,D,E,F,G)分别对应中断线 15~0。这样每个中断线对应了最多 7 个 IO 口,以线 0 为例:它对应了 GPIOA.0、GPIOB.0、GPIOC.0、GPIOD.0、GPIOE.0、GPIOF.0,GPIOG.0。而中断线每次只能连接到 1 个 IO 口上,这样就需要通过配置来决定对应的中断线配置到哪个 GPIO 上了。这样 STM32 把 16 个中断线和 IO 口一一对应起来。
2. 外部中断与中断向量表的关系
一个Px0对应一个中断EXTI0
04引脚对应EXTO04 5个中断
5~9引脚对应EXTO9_5 1个中断
10~15引脚对应EXTO15_10 1个中断
中断初始化 & 中断服务程序
void ExtixInit(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
KeyInitWithGPIO(); //按键对应的IO口初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource0);//PE0–EXTI0
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource2);//PE2–EXTI2
/* 配置EXTI_Line0 */
EXTI_InitStructure.EXTI_Line = EXTI_Line0;//LINE0
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //上升沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能LINE0
EXTI_Init(&EXTI_InitStructure);//配置
EXTI_ClearITPendingBit(EXTI_Line0);
/* 配置EXTI_Line2,3,4 */
EXTI_InitStructure.EXTI_Line = EXTI_Line2;// | EXTI_Line3 | EXTI_Line4;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//中断线使能
EXTI_Init(&EXTI_InitStructure);//配置
EXTI_ClearITPendingBit(EXTI_Line2);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//外部中断0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
NVIC_Init(&NVIC_InitStructure);//配置
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;//外部中断2
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
NVIC_Init(&NVIC_InitStructure);//配置
}
**按钮外部中断有抖动,而消抖没有用:第一次按下,中断标志位置位,进入中断,标志位清零,但是由于按钮抖动,标志位又置位,中断走完,由于标志位没清零,又进入中断,又因为这时候按钮已经不动,不存在抖动,所以第二次中断没有置位标志位,才会进两次中断。**
/*************************
ExTI0 -Px0
*************************/
void EXTI0_IRQHandler(void)
{
if(RESET != EXTI_GetFlagStatus(EXTI_Line0)) //If not use the check status, will enter twice
{
//EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位
delay_ms(10); //消抖
if(KEY1==0)
{
LED1=!LED1; //蜂鸣器翻转
}
EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位
}
}
1.初始化IO口为输入,GPIO_Init
2.使能SYSCFG时钟 系统配置时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE)
3.设置IO口与中断线之间的关系
所谓IO口与中断线
f4中有16个IO中断线,PXn 连接的是 EXITn的中断线
比如现在我要想把 PF9的中断线进行连接,只可以连接EXIT9这个中断
使用函数SYSYCFG_EXTLineConfig()
4.初始化线上中断,设置触发条件(上升沿还是下降沿,是事件还是中断)
EXTI_Init()
5.配置中断分组,并且使能中断
NVIC_Init
6.编写中断服务函数
EXTIx_IRQHandler()
7.清除中断标志
EXTI_ClearTPendingBit();
上拉指的是输入高电平
下拉指的是输入低电平