看野火的视频,用正点原子的板子(STM32F4探索者)做外部中断实验(按下按键反转一次灯的亮灭)

本文详细介绍了如何在STM32F4微控制器上通过GPIOE的KEY0按键控制GPIOF的LED1灯的亮灭操作,涉及GPIO初始化、EXTI中断配置和NVIC处理。通过EXTI的下降沿触发,实现了按键一次控制LED的切换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值