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

猜你喜欢

转载自blog.csdn.net/a1379292747/article/details/128487161