前言
在上一篇STM32F407基础教程7——EXTI简介与库函数中介绍了EXTI的基本概念和相关库函数。本文利用按键来改变引脚的电平状态,通过设置GPIO引脚与中断线的映射关系、配置EXTI相关参数实现外部中断。
工程百度网盘下载链接:STM32F407工程模板(更新至EXTI).rar
链接: https://pan.baidu.com/s/1Ij4eH7do0bYkzpS_QxONVg 提取码: XTLG
1.硬件电路
同按键电路,利用KEY_UP按键按下的过程产生一个下降沿来触发外部中断。KEY_UP连接开发板上的PA0,KEY0连接开发板的PE4。让PA0引脚作为外部中断线0的输入口。
2.程序设计
(1)在工程文件夹下的Hardware文件新建文件夹EXTI,在Keil中新建两个文件EXTI.c和EXTI.h,存放至EXTI文件夹中。
(2)将EXTI.c添加进工程,将EXTI.h添加至头文件路径。
这两步不再详细介绍,具体步骤见STM32F407基础教程4——GPIO口之点亮LED灯中LED.c和LED.h文件的模块化编程操作。
(3)添加stm32f4xx_exti.c文件到项目工程,因为EXTI相关库函数都在该文件中。
添加stm32f4xx_syscfg.c文件到项目工程,因为设置GPIO口与EXTI线映射关系的库函数SYSCFG_EXTILineConfig()在该文件中。
上述步骤效果如下:
(4)编写代码
在main.c文件中定义了变量flag,在主循环中根据flag变量的状态改变LED灯的状态。当按键按下触发中断,进入中断服务函数,在中断服务函数里改变flag变量的状态。
程序执行过程:程序在主循环里执行,当按键按下触发中断后,暂停主程序执行,进入中断服务函数执行,执行完后回到主循环继续执行。
即中断请求-中断响应-中断服务函数-中断返回。
/*EXTI.c文件-EXTI配置代码*/extern u8 flag;void Exti_Init(){/*1-定义NVIC、GPIO、EXTI三个结构体变量*/NVIC_InitTypeDef NVIC_InitStructure;GPIO_InitTypeDef GPIO_InitStruct;EXTI_InitTypeDef EXTI_InitStructure;/*2-开启系统配置时钟、GPIOA时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);/*3-初始化GPIOA0为输入模式*/GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; //A0GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; //输入模式GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; //下拉模式GPIO_Init(GPIOA, &GPIO_InitStruct);/*4-设置GPIOA与EXTI线0的映射关系*/SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);/*5-配置EXTI相关参数*/EXTI_InitStructure.EXTI_Line = EXTI_Line0;//中断线0EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//下降沿触发EXTI_InitStructure.EXTI_LineCmd = ENABLE;//外部中断使能EXTI_Init(&EXTI_InitStructure);/*6-配置NVIC*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//设置中断分组NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//响应优先级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中断NVIC_Init(&NVIC_InitStructure);}/*7-EXTI0中断服务函数*/void EXTI0_IRQHandler(){delay_ms(10);//延时消除抖动,这个函数定义在了KEY.c这个文件了if(EXTI_GetITStatus(EXTI_Line0) != RESET)//判断中断是否响应{flag = ~flag;//进入中断flag变量状态反转EXTI_ClearITPendingBit(EXTI_Line0);//清除中断标志}}
/*EXTI.h*/void Exti_Init(void);
/*main.c*/u8 flag = 0;int main(){LED_Init();Exti_Init();while(1){if(flag == 0) LED0_OFF();//改变灯的状态else LED0_ON();}}

