【stm32----按键中断实验,按键控制LED灯】

stm32----按键中断实验,按键控制LED灯

实验要求

1、按下KEY1,LED1亮,再次按下KEY1,LED1灭;
2、按下KEY2,LED2亮,再次按下KEY2,LED2灭;
3、按下KEY3,LED3亮,再次按下KEY3,LED3灭;

实验代码实现

一、头文件
1、gpio.h

#ifndef __GPIO_H__
#define __GPIO_H__
#define RCC_AHB4_ENSETR (*(volatile unsigned int*)0x50000A28)
typedef struct{
	volatile unsigned int MODER; 	//00
	volatile unsigned int OTYPER; 	//04
	volatile unsigned int OSPEEDR; 	//08
	volatile unsigned int PUPDR; 	//0C
	volatile unsigned int IDR; 		//10
	volatile unsigned int ODR; 		//14
}gpio_t;
#define GPIOE ((gpio_t*)0x50006000)
#define GPIOF ((gpio_t*)0x50007000)
//引脚封装
#define GPIO_PIN_0 0
#define GPIO_PIN_1 1
#define GPIO_PIN_2 2
#define GPIO_PIN_3 3
#define GPIO_PIN_4 4
#define GPIO_PIN_5 5
#define GPIO_PIN_6 6
#define GPIO_PIN_7 7
#define GPIO_PIN_8 8
#define GPIO_PIN_9 9
#define GPIO_PIN_10 10
#define GPIO_PIN_11 11
#define GPIO_PIN_12 12
#define GPIO_PIN_13 13
#define GPIO_PIN_14 14
#define GPIO_PIN_15 15

//封装模式寄存器
typedef enum{
	INPUT,
	OUTPUT,
	ALT,
	ANALOG,
}gpio_mode_t;
 
//封装输出类型寄存器
typedef enum{
	PP,
	OD,
}gpio_otyper_t;
 
//封装输出速度寄存器
typedef enum{
	LOW,
	MED,
	HIGH,
	VERY_HIGH,
}gpio_ospeedr_t;
 
//封装是否需要上下拉电阻
typedef enum{
	NO_PUPD,
	PU,
	PD,
}gpio_pupdr_t;
 
//封装输出高低电平
typedef enum{
	GPIO_RESET,
	GPIO_SET,
}gpio_status_t;

//封装初始化结构体
typedef struct{
	gpio_mode_t moder;	//模式
	gpio_otyper_t otyper;	//输出类型
	gpio_ospeedr_t speed;	//速率
	gpio_pupdr_t pupdr;		//是否需要上下拉电阻
}gpio_init_t;

//函数功能:初始化GPIO
void hal_gpio_init(gpio_t* gpiox,gpio_init_t* init,unsigned int pin);
//函数功能:操作GPIO引脚,实现亮灭
void hal_gpio_write(gpio_t* gpiox,unsigned int pin,gpio_status_t status);
void hal_gpio_turn(gpio_t* gpiox,unsigned int pin);

#endif


2、key.h

#ifndef __KEY_H__
#define __KEY_H__
//#include "stm32mp1xx_gpio.h"
#include "gpio.h"
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_exti.h"
#include "stm32mp1xx_gic.h"

//PF9 key1初始化
void key1_gpio_init();      //GPIO章节初始化
void key1_exti_init();      //EXIT章节初始化
void key1_gicd_init();      //GICD层章节初始化
void key1_gicc_init();      //GICC层章节初始化
//PF7 key2初始化
void key2_gpio_init();      //GPIO章节初始化
void key2_exti_init();      //EXIT章节初始化
void key2_gicd_init();      //GICD层章节初始化
void key2_gicc_init();      //GICC层章节初始化
//PF8 key3初始化
void key3_gpio_init();      //GPIO章节初始化
void key3_exti_init();      //EXIT章节初始化
void key3_gicd_init();      //GICD层章节初始化
void key3_gicc_init();      //GICC层章节初始化
#endif

二、初始化函数及功能函数
1、gpio.c

#include "gpio.h"
//初始化GPIO
void hal_gpio_init(gpio_t* gpiox,gpio_init_t* init,unsigned int pin)
{
    //设置输出模式
    gpiox->MODER &=(~(0x3<<(pin*2)));
    gpiox->MODER |=(init->moder<<(pin*2));
    //设置输出类型
    gpiox->OTYPER &=(~(0x1<<pin));
    gpiox->OTYPER |=(init->otyper<<pin);
    //设置输出速率
    gpiox->OSPEEDR &=(~(0x3<<(pin*2)));
    gpiox->OSPEEDR |=(init->speed<<(pin*2));
    //是否上下拉电阻
    gpiox->PUPDR &=(~(0x3<<(pin*2)));
    gpiox->PUPDR |=(init->pupdr<<(pin*2));
}
//函数功能:操作GPIO引脚,实现亮灭
void hal_gpio_write(gpio_t* gpiox,unsigned int pin,gpio_status_t status)
{
    if(status==GPIO_SET)
    {
        gpiox->ODR |=(0x1<<pin);
    }
    else
    {
        gpiox->ODR &=(~(0x1<<pin));
    }
}
//按键交替亮灭
void hal_gpio_turn(gpio_t* gpiox,unsigned int pin)
{
    if((gpiox->ODR & (0x1<<pin))==0)
    {
        gpiox->ODR |=(0x1<<pin);
    }
    else
    {
        gpiox->ODR &=(~(0x1<<pin));
    }
}

2、key.c

#include "key.h"
/************key1初始化*************/
void key1_gpio_init()
{
    /****RCC章节初始化*******/
	//1.设置GPIOF组时钟使能
	RCC->MP_AHB4ENSETR |= (0x1 << 5);
	/****GPIO章节初始化*******/
	//1.设置PF9引脚为输入模式
	GPIOF->MODER &= (~(0x3 << 18));
}
void key1_exti_init()
{
    //设置PF9引脚与EXTI9控制器连接
    EXTI->EXTICR3 &=(~(0xff)<<8);
    EXTI->EXTICR3 |=(0x5<<8);
    //设置PF9引脚下降沿触发
    EXTI->FTSR1 |=(0x1<<9);
    //设置PF9引脚中断不屏蔽
    EXTI->C1IMR1 |=(0x1<<9);
}
void key1_gicd_init()
{
    //设置全局使能寄存器
    GICD->CTRL |=(0x1<<0);
    //设置中断使能寄存器
    GICD->ISENABLER[3] |=(0x1<<3);
    //设置GICD层中断优先级寄存器
    GICD->IPRIORITYR[24] &=(0x1f<<27);
    GICD->IPRIORITYR[24] |=(0x1<<27);
    //设置中断目标分配寄存器
    GICD->ITARGETSR[24] |=(0x3<<24);
}
void key1_gicc_init()
{
    //设置全局使能寄存器
    GICC->CTRL |=(0x1<<0);
    //设置GICC层中断优先级值
    GICC->PMR &=(~(0x1f)<<3);
    GICC->PMR |=(0x4<<3);
}
/************key2初始化*************/
void key2_gpio_init()
{
    //1.设置PF7引脚为输入模式
	GPIOF->MODER &= (~(0x3 << 14));
}
void key2_exti_init()
{
    //设置PF7引脚与EXTI7控制器连接
    EXTI->EXTICR2 &=(~(0xff<<24));
    EXTI->EXTICR2 |=(0x5<<24);
    //设置PF7引脚下降沿触发
    EXTI->FTSR1 |=(0x1<<7);
    //设置PF7引脚中断不屏蔽
    EXTI->C1IMR1 |=(0x1<<7);
}
void key2_gicd_init()
{
    //设置全局使能寄存器
    GICD->CTRL |=(0x1<<0);
    //设置中断使能寄存器
    GICD->ISENABLER[3] |=(0x1<<1);
    //设置GICD层中断优先级寄存器
    GICD->IPRIORITYR[24] &=(0x1f<<11);
    GICD->IPRIORITYR[24] |=(0x2<<11);
    //设置中断目标分配寄存器
    GICD->ITARGETSR[24] |=(0x3<<8);
}
void key2_gicc_init()
{
    //设置全局使能寄存器
    GICC->CTRL |=(0x1<<0);
    //设置GICC层中断优先级值
    GICC->PMR &=(~(0x1f)<<3);
    GICC->PMR |=(0x5<<3);
}
/************key3初始化*************/
void key3_gpio_init()
{
    //1.设置PF8引脚为输入模式
	GPIOF->MODER &= (~(0x3 << 16));
}
void key3_exti_init()
{
    //设置PF8引脚与EXTI9控制器连接
    EXTI->EXTICR3 &=(~(0xff)<<0);
    EXTI->EXTICR3 |=(0x5<<0);
    //设置PF8引脚下降沿触发
    EXTI->FTSR1 |=(0x1<<8);
    //设置PF8引脚中断不屏蔽
    EXTI->C1IMR1 |=(0x1<<8);
}
void key3_gicd_init()
{
    //设置全局使能寄存器
    GICD->CTRL |=(0x1<<0);
    //设置中断使能寄存器
    GICD->ISENABLER[3] |=(0x1<<2);
    //设置GICD层中断优先级寄存器
    GICD->IPRIORITYR[24] &=(0x1f<<19);
    GICD->IPRIORITYR[24] |=(0x3<<19);
    //设置中断目标分配寄存器
    GICD->ITARGETSR[24] |=(0x3<<16);
}
void key3_gicc_init()
{
    //设置全局使能寄存器
    GICC->CTRL |=(0x1<<0);
    //设置GICC层中断优先级值
    GICC->PMR &=(~(0x1f)<<3);
    GICC->PMR |=(0x6<<3);
}

三、中断处理函数
do_irq.c

#include "key.h"
extern void printf(const char *fmt, ...);
extern void delay_ms(int ms);
unsigned int i = 0;
void do_irq(void)
{
    unsigned int num = 0;
    // 获取中断号
    num = GICC->IAR;
    switch (num)
    {
    case 97:
        delay_ms(500);
        printf("key2 is pressed  \n");
        hal_gpio_turn(GPIOF, GPIO_PIN_10);
        // 清除EXTI层中断挂起标志位
        EXTI->FPR1 |= (0x1 << 7);
        // 清除GICD层中断挂起标志位
        GICD->ICPENDR[3] |= (0x1 << 1);
        break;

    case 98:
        delay_ms(500);
        printf("key3 is pressed  \n");
        hal_gpio_turn(GPIOE, GPIO_PIN_8);
        // 清除EXTI层中断挂起标志位
        EXTI->FPR1 |= (0x1 << 8);
        // 清除GICD层中断挂起标志位
        GICD->ICPENDR[3] |= (0x1 << 2);
        break;
    case 99:
        delay_ms(500);
        printf("key1 is pressed  \n");
        hal_gpio_turn(GPIOE, GPIO_PIN_10);
        // 清除EXTI层中断挂起标志位
        EXTI->FPR1 |= (0x1 << 9);
        // 清除GICD层中断挂起标志位
        GICD->ICPENDR[3] |= (0x1 << 3);
        break;
    }
    // 清除中断号
    GICC->EOIR &= (0x3ff << 0);
    GICC->EOIR |= num;
}

四、主函数
main.c

#include "key.h"
extern void printf(const char *fmt, ...);
void delay_ms(int ms)
{
	int i,j;
	for(i = 0; i < ms;i++)
		for (j = 0; j < 1800; j++);
}

void LED_init()
{
	//时钟使能
	RCC_AHB4_ENSETR |=(0x3<<4);
	//RCC_AHB4_ENSETR |=(0x1<<5);
	//初始化结构体
	gpio_init_t init={OUTPUT,PP,LOW,NO_PUPD};
	//LED初始化
	hal_gpio_init(GPIOE,&init,GPIO_PIN_10);		//LED1
	hal_gpio_init(GPIOF,&init,GPIO_PIN_10);		//LED2
	hal_gpio_init(GPIOE,&init,GPIO_PIN_8);		//LED3
}
int main()
{
	LED_init();
	/**********key1初始化************/
	key1_exti_init();
	key1_gicc_init();
	key1_gicd_init();
	key1_gpio_init();
	/**********key2初始化************/
	key2_exti_init();
	key2_gicc_init();
	key2_gicd_init();
	key2_gpio_init();
	/**********key3初始化************/
	key3_exti_init();
	key3_gicc_init();
	key3_gicd_init();
	key3_gpio_init();
	while(1)
	{
		
	}
	return 0;
}

实验结果

依次按下key3、key2、key1、key2
在这里插入图片描述
结果应该为LED3、LED1亮,LED2灭;
请添加图片描述

  • 6
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
STM32是一款基于ARM Cortex-M系列内核的32位微控制器,可用于开发嵌入式系统。按键中断LED亮灭是嵌入式系统中非常常见的功能,下面我将用300字回答如何使用STM32按键中断控制LED的亮灭。 首先,我们需要连接一个按键和一个LEDSTM32控制器的相应引脚上。假设按键连接到PA0引脚,LED连接到PC13引脚。 接下来,我们需要配置STM32的GPIO外设来控制这些引脚。首先,开启相关引脚的时钟。然后,将PA0引脚配置为输入模式,PC13引脚配置为输出模式。可以使用STM32的寄存器或者开发环境提供的库函数来完成这些配置。 然后,我们需要配置外部中断。配置PA0引脚所对应的外部中断线,使其可以检测到按键的状态变化。可以使用STM32的寄存器或者库函数来完成这个配置。 紧接着,我们编写中断处理函数。当按键状态发生变化,中断触发时,中断处理函数被调用。在该函数中,我们可以读取按键引脚的状态,如果按键被按下,我们将PC13引脚设置为高电平,LED亮起;如果按键被释放,我们将PC13引脚设置为低电平,LED熄灭。 最后,我们需要在主函数中启用中断。启用中断后,当按键状态发生变化时,中断处理函数将被调用。 以上就是使用STM32按键中断控制LED亮灭的步骤。通过配置GPIO外设和外部中断,编写中断处理函数,我们能够实现按下按键时,LED亮起;释放按键时,LED熄灭的功能。这样就完成了按键中断控制LED亮灭的任务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Holy meat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值