1.实验目的
按下按键KEY0,灯LED1亮,再按一下按键KEY0,灯LED1灭。这里的KEY0的端口是GPIOE,引脚就是PIN4。LED1的端口是GPIOF,引脚是PIN10。
如下图所示:
2.实验流程
1. 初始化LED和KEY
1.1 初始化LED1
//初始化LED1
//里是GPIO的速度,上下拉,输出类型
GPIO_InitTypeDef GPIO_InitStruct;
//打开时钟(一般开时钟要放到前面的位置,然后再是设置上拉,输出这些)
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE); //使能时钟必须放到前面,不然后面的操作不会使灯点亮
//驱动是哪个引脚 PF10
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
//推挽输出
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
//上拉
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
//输出的速度
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
//变量获取它的指针,取地址就行(&)
GPIO_Init(GPIOF,&GPIO_InitStruct);
GPIO_SetBits(GPIOF,GPIO_Pin_10);//GPIOF10设置高,灯灭
1.2 初始化KEY0
GPIO_InitTypeDef GPIO_InitStruct;
//打开时钟(一般开时钟要放到前面的位置,然后再是设置上拉,输出这些)
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
//驱动是哪个引脚 PE4
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;
//输入
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
//上拉
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //看标准库函数里面找的
//变量获取它的指针,取地址就行(&)
GPIO_Init(GPIOE,&GPIO_InitStruct);
2. 初始化EXTI(外部中断/事件控制器)用于产生中断/事件
2.1 打开SYSCFG 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能 SYSCFG 时钟
2.2 配置GPIO 与中断线的映射关系
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource4);//中断线4与GPIOE连接起来了,PE4 连接线 4
2.3 初始化EXTI结构体,设置是上升沿捕获还是下降沿捕获
//EXTI结构体
EXTI_InitTypeDef EXTI_InitStruct;EXTI_InitStruct.EXTI_Line = EXTI_Line4; //GPIO连接的是哪条输入线line
EXTI_InitStruct.EXTI_LineCmd = ENABLE; //使能输入线line(中断线)
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; //配置为中断模式
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; //这里按下是低电平,就是检测下降沿EXTI_Init(&EXTI_InitStruct);
3. 初始化NVIC(嵌套向量中断控制器),用于处理中断
NVIC_InitTypeDef NVIC_InitStruct;
//设置中断优先级的分组
//就是设置主抢占优先级和子抢占优先级各是几,这里是分组为1,代表主优先级可以是0和1(就是1个位来设置主优先级),子优先级是0-7,是2的3次方
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStruct.NVIC_IRQChannel = EXTI4_IRQn; //为什么是4,这里是GPIOE,pin4所以这里选4
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//使能
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; //这里是抢占优先级,配置成0和1都可以 Preemption:抢占的意思 0x01
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; //子优先级 0x01
NVIC_Init(&NVIC_InitStruct);
4.编写中断服务函数(写在stm32f4xx_it.c里面)
void EXTI4_IRQHandler(void){
//判断中断是否产生 看EXTI_GetITStatus()的返回值
//判断某个中断线上的中断是否发生(标志位是否置位)
if(EXTI_GetITStatus(EXTI_Line4)!=RESET){ //RESET = 0, SET = !RESET,不为0就是set
LED_G_TOGGLE;
}
//清除中断位
EXTI_ClearITPendingBit(EXTI_Line4); //清除 LINE 上的中断标志位
}
这里的LED_G_TOGGLE是在LED.h里面定义的宏,用来反转LED灯的。
#define LED_G_TOGGLE {GPIOF->ODR ^=GPIO_Pin_10;}
3.代码展示
3.1 exti.c文件代码
#include "exti.h"
void EXTI_NVIC_Config(void){
//设置结构体
NVIC_InitTypeDef NVIC_InitStruct;
//设置中断优先级的分组
//就是设置主抢占优先级和子抢占优先级各是几,这里是分组为1,代表主优先级可以是0和1(就是1个位来设置主优先级),子优先级是0-7,是2的3次方
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStruct.NVIC_IRQChannel = EXTI4_IRQn; //为什么是4,这里是GPIOE,pin4所以这里选4
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; //这里是抢占优先级,配置成0和1都可以 Preemption:抢占的意思 0x01
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; //子优先级 0x01
NVIC_Init(&NVIC_InitStruct);
}
void EXTI_Key_Config(void){ //其他文件的函数是调用不了的,加了关键字static//1.初始化要连接到EXTI的GPIO,就是KEY的GPIO引脚,PE4对应的是KEY0
//初始化结构体 GPIO_InitStruct(取的一个随机的名字)
//里面是GPIO的速度,上下拉,输出类型
GPIO_InitTypeDef GPIO_InitStruct;
//EXTI结构体
EXTI_InitTypeDef EXTI_InitStruct;
//打开时钟(一般开时钟要放到前面的位置,然后再是设置上拉,输出这些)
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
//驱动是哪个引脚 PE4
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;
//输入
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
//上拉
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;//看标准库函数里面找的//输入的速度 输入没有速度之说
//GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
//变量获取它的指针,取地址就行(&)
GPIO_Init(GPIOE,&GPIO_InitStruct);
//2. 初始化EXTI用于产生中断/事件
//2.1 只要我们使用到外部中断,就必须打开 SYSCFG 时钟,库函数手册里面
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能 SYSCFG 时钟
//2.2 选择输入线 配置GPIO 与中断线的映射关系的函数 SYSCFG_EXTILineConfig()来实现的
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource4);//中断线4与GPIOE连接起来了 //PE4 连接线 4
//2.3 初始化EXTI结构体,就是设置是捕获上升还是下降
EXTI_InitStruct.EXTI_Line = EXTI_Line4; //GPIO连接的是哪条输入线line
EXTI_InitStruct.EXTI_LineCmd = ENABLE; //使能输入线line(中断线)
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; //配置为中断模式
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; //这里按下是低电平,就是检测下降沿
//把上面的配置写到寄存器里面
EXTI_Init(&EXTI_InitStruct);
//3.初始化NVIC,用于处理中断
//配置中断优先级
EXTI_NVIC_Config();
}
3.2 stm32f4xx_it.c文件代码
void EXTI4_IRQHandler(void){
//判断中断是否产生 看EXTI_GetITStatus()的返回值
//判断某个中断线上的中断是否发生(标志位是否置位)
if(EXTI_GetITStatus(EXTI_Line4)!=RESET){ //RESET = 0, SET = !RESET,不为0就是set
LED_G_TOGGLE;
}
//清除中断位
EXTI_ClearITPendingBit(EXTI_Line4); //清除 LINE 上的中断标志位
}
3.3 main.c文件代码
int main(void)
{LED_GPIO_Config();
EXTI_Key_Config();
while(1){}
}
4.结果展示
VID_20221221_155330