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灭;
    请添加图片描述

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32按键中断实验:用按键控制LED灯

    发表评论