STM32F4 的每个 IO 都可以作为外部中断输入,很强大的功能吧!以前学习的 51 只有两个外部中断。
STM32F4 的中断控制器支持 22 个外部中断 / 事件请求:
EXTI 线 0~15:对应外部 IO 口的输入中断。即 GPIOx.0—EXTI0,GPIOx.a—EXTIa 如下图所示
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 唤醒事件。
对于每个中断线 0 我们可以设置相应的触发方式(上升沿触发,下降沿触发,边沿触发)以及使能。
中断服务函数又是如何分配的呢
其中中断线 0-4 有单独的中断向量,即单独的中断服务函数。
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
中断线 5-9 共用一个中断服务函数
EXTI9_5_IRQHandler
中断线 10-15 共同一个中断服务函数
EXTI15_10_IRQHandler
嵌套向量中断控制器 NVIC (Nested vectored interrupt controller)
中断优先级分组的是在 SCB->AIRCR 寄存器中设置的,具体设置情况如下:
选择不同的分组可以设置不同的优先级等级,例如选择分组 2,分配结果为 2 位抢占,2 位响应,既然是两位,所以优先级可以设置为 0-3,要注意的是,设置好分组之后不要再改变分组,随意改变分组会导致中断管理混乱。
关于抢占优先级和响应优先级的说明
例如:
这里要注意的是,抢占优先级设置的越小,则优先级越高,0 最高
则这三个优先级的顺序为:中断 7 > 中断 3 > 中断 6。
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); //使能GPIOA,GPIOE时钟
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //普通输入模式
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
- GPIO_Init(GPIOE, &GPIO_InitStructure);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); //使能SYSCFG时钟,必须的
- SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3); //PF3,中断线映射,line3-Pin3
- EXTI_InitTypeDef EXTI_InitStructure; //中断方式初始化
- EXTI_InitStructure.EXTI_Line = EXTI_Line3; //指定中断线3
- EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能中断线
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发方式,必须的,上升沿不灵敏
- EXTI_Init(&EXTI_InitStructure);
- NVIC_InitTypeDef NVIC_InitStructure; //优先级初始化
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断分组为2:2,优先级范围0-3
- NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn; //指定中断线3
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道使能
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级0,可以设置0-3
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级0,可以设置0-3
- NVIC_Init(&NVIC_InitStructure);
中断初始化完毕后,就可以编写相应的中断服务函数了,我们使用的是中断线 3,所以对应的中断服务函数名称为 void EXTI3_IRQHandler(void),注意在执行完后要将标志位清零,
- void EXTI3_IRQHandler(void) //中断线3服务函数,发生中断时,自动执行
- {
- delay_ms(10); //消抖,很有必要,增加识别的准确度
- if(KEY1 == 0) //用EXTI_GetITStatus(EXTI_Line3)!=RESET来判断不是很灵敏,快速按时不准确
- LED0 = !LED0;
- EXTI_ClearITPendingBit(EXTI_Line3); //清除LINE3上的中断标志位,以备下一次使用
- }
根据手册可以通过 EXTI_GetITStatus(EXTI_Line3) 来判断中断标志位的状态, 实际运行时发现这种方式并不是很有效,可能是我的用法不对吧!
这个中断服务函数还是很简单的,就是按下按键时,将 LED 的状态反转
主函数的执行部分可以不写,这里写了 LED 的闪烁用来指示程序的运行
- int main(void)
- {
- delay_init(168);
- LED_Init();
- IT_Init(); //中断初始化
- LED0_OFF;
- LED1_OFF;
- while(1)
- {
- LED1_ON;
- delay_ms(500); //LED1闪烁提醒程序运行状态
- LED1_OFF;
- delay_ms(500);
- }
- }
从以上过程可以看出 STM32F4 的外部中断的配置和使用方法还是很简单清晰的。虽然比 51 要复杂一些,但是毕竟功能那么强大,复杂一些也是可以理解的。
STM32F4xx 中文参考手册
STM32F4 开发指南 - 库函数版本_V1.1
2017 年 4 月 17 日 22:01:43
来源: http://www.cnblogs.com/whik/p/6725185.html