STM32F429中有10个系统异常,91个中断。
EXTI——外部中断/事件控制器
有图可得:EXTI可以产生中断也可以产生事件
编写按键——中断驱动程序
-
初始化RGB彩色灯(前面的LED驱动程序已经写好了,直接调用就可以了)
-
打开GPIO的时钟和SYSCFG时钟(SYSCFG是外部中断寄存器,使用EXTI必须开启SYSCFG时钟)
-
配置NVIC
NVIC是嵌套向量中断控制器,设置中断优先级别。NVIC的函数声明在misc.h这个头文件里。首先设置NVIC的优先级组,然后初始化NVIC。 IRQchannel是中断通道,初始化首先就要选择中断源,中断源填写的是中断号,中断号在stm32f4xx.h的头文件。使能中断源,设置中断源的抢占优先级和子优先级。(我写的中断不是很多所以抢占优先级和子优先级设置的很随意))
补充一下:如何比较优先级:先比较优先级组,再比较抢占优先级,再比较子优先级void NVIC_configue(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitTypeDef NVIC_InitStruct; NVIC_InitStruct.NVIC_IRQChannel= EXTI0_IRQn; NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority= 1; NVIC_InitStruct.NVIC_IRQChannelSubPriority= 1; NVIC_Init(&NVIC_InitStruct); }
-
配置按键为输入模式(前面Key的驱动程序已经写好了,可以直接调用)
-
将按键GPIO连接到EXTI源输入
前面说过SYSCFG是系统配置控制器,去手册看SYSCFG外部中断配置寄存器的功能是什么?EXTI x 配置(EXTI x configuration)这些位通过软件写入,以选择 EXTIx 外部中断的源输入。SYSCFG的函数声明在syscfg.h这个头文件里,有函数命名可以找到函数:void SYSCFG_EXTILineConfig(uint8_t EXTI_PortSourceGPIOx, uint8_t EXTI_PinSourcex);
-
配置按键的EXTI中断/事件(上面的框图有介绍产生事件和产生中断的路径)
EXTI是外部中断/事件控制器,初始化EXTI。EXTI_Line这是EXTI的中断线,要如何赋值要看手册,GPIO口对应的中断线可能会不一样。根据开发板原理图按键KEY1
是PA0口,则对应的中断线是EXTI0。然后使能中断线,配置是产生中断还是产生事件,电平的触发方式。
void EXTI_confiue (void) { EXTI_InitTypeDef EXTI_InitStruct; EXTI_InitStruct.EXTI_Line=EXTI_Line0; EXTI_InitStruct.EXTI_LineCmd=ENABLE; EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt; EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Rising; EXTI_Init(&EXTI_InitStruct); }
-
编写中断服务函数
在启动文件中为每一个中断都写了中断函数,但是这些中断函数是空的,只是为了初始化中断向量表,当用到这些中断函数的时候要自己重新编写。记得自己写的中断函数的名字一定要和启动文件里的中断函数名一样,否则,执行的时候在中断向量表中找不到中断服务函数入口,直接跳到启动文件的中断函数里一直死循环,实现不了中断。中断函数其实写在哪里都可以,不一定要写在stm32f4xx_it.c 中,看个人习惯。stm32f4xx_it.c中有中断函数的格式,可以参考一下。
用这个函数判断是否进入中断ITStatus EXTI_GetITStatus(uint32_t EXTI_Line) ;进入中断返回1,否返回0;每次执行任务后就要清楚中断标志位,调用void EXTI_ClearITPendingBit(uint32_t EXTI_Line) ;void EXTI0_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line0) == SET) //判断是否进入中断 { } EXTI_ClearITPendingBit(EXTI_Line0); //清除中断标志位 }
完整代码如下:
void EXTI_key_configue(void)
{
LED_GPIO_Config();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
NVIC_configue();
KEY_config();
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
EXTI_confiue ();
}
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) == SET) //判断是否进入中断
{
LEDB_TOGGLE;//蓝灯翻转
}
EXTI_ClearITPendingBit(EXTI_Line0); //清除中断标志位
}