外部中断EXTI和NVIC

📅 2026/6/24 5:25:51
外部中断EXTI和NVIC
一、外部中断/事件控制器框图输入线是EXTI即外部中断源外部中断源有20个中断(事件线) 即输入线上有20个事件线0-15是GPIO的16-19是一些特殊的外部中断外部中断通用I/O映像1.输入线(20条事件线选一条)2.边沿检测电路(此时连接着上升沿触发选择寄存器和下降沿触发选择寄存器,选一个外部中断用于IO口高低电平变化)(0和1分别表示低电平和高电平而信号在低电平一段时间然后在一个时刻从0低电平突然到1高电平然后一段时间的高电平后在一时刻从高电平突然变到低电平上升沿是低电平变成高电平的过程即上升沿就是信号从低电平0跳变到高电平1的那一瞬间,下降沿是高电平到低电平的的过程)3.NVIC中断控制器(内核外设)二、配置中断步骤1.初始化用来中断的GPIO口2.初始化EXTI(外部中断源)3.配置NVIC(中断优先级)4.编写中断服务函数1.配置GPIO的结构体2.初始化EXTI(外部中断源)在exti.h文件里找到结构体EXTI_InitTypeDef;结构体成员详解1. EXTI_LineEXTI中断/事件线选择可选EXTI0 ~ EXTI19定义在 stm32f10x_exti.h2. EXTI_ModeEXTI模式选择二选一产生中断模式 / 产生事件模式(一般选择中断)3. EXTI_Trigger边沿触发配置可选上升沿触发、下降沿触发、双边沿上升下降触发4. EXTI_LineCmdEXTI线路开关控制使能EXTI线 / 禁用EXTI线3.在misc.c文件里misc.h找到NVIC中断优先级的结构体结构体成员详解1. NVIC_IRQChannel指定要配置的中断通道相关定义在 misc.h 例如EXTI0、USART1、TIM2等各类外设中断。不同的组别优先级不一样2. NVIC_IRQChannelPreemptionPriority抢占优先级高抢占优先级中断可以打断当前正在执行的低抢占优先级中断实现中断嵌套。数字越小的地位越高3. NVIC_IRQChannelSubPriority子优先级响应优先级抢占优先级相同时子优先级数值越小中断优先响应无法实现中断嵌套。4. NVIC_IRQChannelCmd中断通道开关取值 ENABLE 使能4.编写中断服务函数写好的中断服务函数三、代码编写基于之前的项目,首先创建exti文件夹创建exti.c和exti.h文件然后在c文件包含的头文件和固件库然后函数定义(中断服务函数)在.h文件里面包含固件库和函数声明在main.c文件里包含exti.h文件,在USER文件夹里面,exti.h在exti文件夹没有和main.c文件所在的文件夹在一起需要添加路径(魔术棒include paths找到exti.h所在文件夹即可)void exti_init(void) { 1.初始化用来中断的GPIO口(用到的是震动传感器PA1选择之前项目的shake_inie()函数体配置GPIO) GPIO_InitTypeDef shake_init;//初始化结构体 EXTI_InitTypeDef exti_init;//初始化结构体 NVIC_InitTypeDef nvic_init;//初始化结构体 //打开GPIOA时钟(DO选择链接到A1引脚) RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//GPIO的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//外部中断的时钟 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSouurcel);//设置GPIOA1口设置成GPIO的外部中断源(外部中断线的配置) NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//把4个优先级bit切成两半——2bit给抢占优先级(0, 1, 2, 3)2 bit 给子优先级。 //配置结构体 shake_init.GPIO_ModeGPIO_Mode_IPD; shake_init.GPIO_PinGPIO_Mode_Pin_1; shake_init.GPIO_SpeedGPIO_Speed_10MHz; //初始化函数 GPIO_Init(GPIOA, shake_init); 2.初始化EXTI(外部中断源) exti_init.EXTI_LineEXTI_Line1;//用到的是GPIOA1,所以选Line1 exti_init.EXTI_ModeEXTI_Mode_Interrupt;//选择中断模式 exti_init.EXTI_TriggerEXTI_Trigger_Falling;//震动传感器正常处于高电平发生震动变成低电平选择下降沿 exti_init.EXTI_LineCmdENABLE; EXTI_Init(exti_init); 3.配置NVIC(中断优先级) //初始化函数 NVIC_Init(nvic_init); nvic_init.NVIC_IRQChannel EXTI1_IRQn ; //GPIOA1 → Pin_1 →EXTI_Line1→IRQ通道:EXTI1_IRQn→函数:EXTI1_IRQHandler引脚编号 EXTI 线编号一一对应。 nvic_init.NVIC_IRQChannelPreemptionPriority1;对应图表示在0~3 里随便选 nvic_init.NVIC_IRQChannelSubPriority1;//0~3 里随便选 nvic_init.NVIC_IRQChannelCmdENABLE; NVIC_Init(nvic_init); 4.编写中断服务函数 }在main.c添加中断函数 void EXTI1_IRQHandler(void) { if (EXTI_GetITStatus(EXTI_Line1)!RESET)//发生中断(RESET 0)震动传感器产生高电平 { GPIO_ResetBits(GPIOA,GPIO_Pin_3);打开继电器开灯 delay(1000); GPIO_SetBits(GPIOA,GPIO_Pin_3);关闭继电器关灯 } EXTI_ClearFla(EXTI_Line1);// 发生中断后会有中断标志,中断服务函数最后一定要清标志不然一退出又重新进中断死循环 }