key.h:
cpp
#ifndef __KEY_H_
#define __KEY_H_
#include "stm32mp1xx_rcc.h"
#include "gpio.h"
#include "stm32mp1xx_exti.h"
#include "stm32mp1xx_gic.h"
//中断触发方式
typedef enum{
FALLING,
RISING
}trigger_t;
//RCC章节初始化
void hal_interrupt_rcc_init();
//GPIO/EXTI章节初始化
void hal_exti_init(unsigned int EXTI_event,
unsigned int GPIOx_group,trigger_t trigeer);
//GIC章节初始化
void hal_gic_init(unsigned int interrupt_id,unsigned int pro);
#endif
gpio.h:
cpp
#ifndef __GPIO_H__
#define __GPIO_H__
//防止头文件重复包含
//LED1-->PE10
//LED2-->PF10
//LED3-->PE8
//RCC_MP_AHB4ENSETR寄存器封装
#define RCC_MP_AHB4ENSETR (*(volatile unsigned int*)0x50000A28)
//GPIO使用结构体封装
typedef struct{
unsigned int MODER; //0x00
unsigned int OTYPER; //0x04
unsigned int OSPEEDR; //0x08
unsigned int PUPDR; //0x0c
unsigned int IDR; //0x10
unsigned int ODR; //0x14
}gpio_t;
#define GPIOE ((volatile gpio_t*)0x50006000) //GPIOE基地址
#define GPIOF ((volatile gpio_t*)0x50007000) //GPIOF基地址
//引脚编号进行封装
#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
//使用枚举封装MODER模式寄存器(INPUT/OUTPUT/ALT/ANALOG)
typedef enum{
INPUT, // 输入 0
OUTPUT, //输出 1
ALT, // 复用 2
ANALOG //模拟 3
}gpio_moder_t;
//使用枚举封装OTYPER寄存器
typedef enum{
PP, // 推挽 0
OD // 开漏 1
}gpio_otyper_t;
//使用枚举封装OSPEEDR寄存器
typedef enum{
LOW, //低速 0
MED, // 中速 1
HIGH, // 高速 2
VERY_HIGH // 快速 3
}gpio_ospeedr_t;
//使用枚举封装PUPDR寄存器
typedef enum{
NO_PUPDR, // 禁止上下拉电阻 0
PU, // 上拉 1
PD // 下拉 2
}gpio_pupdr_t;
//封装初始化结构体
typedef struct{
gpio_moder_t moder;//模式寄存器
gpio_otyper_t otyper;//输出类型寄存器
gpio_ospeedr_t ospeedr;//输出速率寄存器
gpio_pupdr_t pupdr;//是否需要上下拉电阻寄存器
}gpio_init_t;
//使用枚举封装ODR寄存器
typedef enum{
GPIO_RESET_T, // 熄灭 0
GPIO_SET_T // 点亮 1
}gpio_status_t;
//函数功能:GPIO引脚初始化操作
//参数1:GPIO组号
//参数2:引脚编号
//参数3:初始化内容
void hal_gpio_init(volatile gpio_t* gpiox,unsigned int pin,gpio_init_t* init);
//函数功能:GPIO引脚操作 写1 灯点亮 写0 灯熄灭
//参数1:GPIO组号
//参数2:引脚编号
//参数3:写的内容
void hal_gpio_write(volatile gpio_t* gpiox,unsigned int pin,gpio_status_t status);
#endif
key.c:
cpp
#include "key.h"
//RCC/GPIO/EXTI章节初始化
void hal_interrupt_rcc_init()
{
//RCC章节初始化
//1.使能GPIOF组控制器 MP_AHB4ENSETR[5] = 1
RCC->MP_AHB4ENSETR |= (0x1 << 5);
}
//RCC/GPIO/EXTI章节初始化
void hal_exti_init(unsigned int EXTI_event,
unsigned int GPIOx_group,trigger_t trigeer)
{
//设置三个按键为输入模式
GPIOF->MODER &= (~(0x3 << (EXTI_event * 2)));
//EXTI章节初始化
//1.设置GPIO引脚与EXTIz组进行连接EXTICRn
switch(EXTI_event / 4)
{
case 0:
EXTI->EXTICR1 &= (~(0xff << (EXTI_event % 4 * 8)));
EXTI->EXTICR1 |= (GPIOx_group << (EXTI_event % 4 * 8));
break;
case 1:
EXTI->EXTICR2 &= (~(0xff << (EXTI_event % 4 * 8)));
EXTI->EXTICR2 |= (GPIOx_group << (EXTI_event % 4 * 8));
break;
case 2:
EXTI->EXTICR3 &= (~(0xff << (EXTI_event % 4 * 8)));
EXTI->EXTICR3 |= (GPIOx_group << (EXTI_event % 4 * 8));
break;
case 3:
EXTI->EXTICR4 &= (~(0xff << (EXTI_event % 4 * 8)));
EXTI->EXTICR4 |= (GPIOx_group << (EXTI_event % 4 * 8));
break;
}
//2.设置三个按键为下降沿触发方式 FTSR1
if(trigeer == FALLING)
{
EXTI->FTSR1 |= (0x1 << EXTI_event);
}else
{
EXTI->RTSR1 |= (0x1 << EXTI_event);
}
//3.设置EXTI中断不屏蔽 C1IMR1
EXTI->C1IMR1 |= (0x1 << EXTI_event);
}
//GIC章节初始化
void hal_gic_init(unsigned int interrupt_id,unsigned int pro)
{
//GICD章节初始化
//1.设置GICD层中断设置使能寄存器
GICD->CTRL |= (0x1 << 0);
GICD->ISENABLER[interrupt_id / 32] |= (0x1 << (interrupt_id % 32));
//2.设置GICD层中断优先级寄存器 IPRIORITYR
GICD->IPRIORITYR[interrupt_id / 4] &= (~(0x1f << (interrupt_id % 4 * 8 + 3)));
GICD->IPRIORITYR[interrupt_id / 4] |= (pro << (interrupt_id % 4 * 8 + 3));
//3.设置中断目标分配寄存器 ITARGETSR[24]
GICD->ITARGETSR[interrupt_id / 4] &= (~(0x3 << (interrupt_id % 4 * 8)));
GICD->ITARGETSR[interrupt_id / 4] |= (0x1 << (interrupt_id % 4 * 8));
//GICC章节初始化
//1.设置GICC层中断设置使能寄存器 CTRL[0] = 1
GICC->CTRL |= (0x1 << 0);
//2.设置GICC层中断优先级寄存器 PMR[7:3] = 0b11111
GICC->PMR |= (0x1f << 3);
}
do_irq:
cpp
#include "stm32mp1xx_gic.h"
#include "stm32mp1xx_exti.h"
#include "gpio.h"
extern void printf(const char *fmt, ...);
//中断处理函数
void do_irq(void)
{
unsigned int num;
//1.获取中断号 IAR[9:0]
num = GICC->IAR & (0x3ff);
//2.判断中断号,并且打印一句话
switch(num)
{
case 97:
printf("key2 down!!!!\n");
GPIOF->ODR ^= (0x1 << 10); //LED2
//3.清除EXTI层中断挂起标志位 FPR1[7] = 1
EXTI->FPR1 |= (0x1 << 7);
//4.清除GICD层中断挂起标志位 ICPENDR[3]第1位
GICD->ICPENDR[3] |= (0x1 << 1);
break;
case 98:
printf("key3 down!!!!\n");
GPIOE->ODR ^= (0x1 << 10); //LED1
//3.清除EXTI层中断挂起标志位 FPR1[8] = 1
EXTI->FPR1 |= (0x1 << 8);
//4.清除GICD层中断挂起标志位 ICPENDR[3]第2位
GICD->ICPENDR[3] |= (0x1 << 2);
break;
case 99:
printf("key1 down!!!!\n");
GPIOE->ODR ^= (0x1 << 8); //LED3
//3.清除EXTI层中断挂起标志位 FPR1[9] = 1
EXTI->FPR1 |= (0x1 << 9);
//4.清除GICD层中断挂起标志位 ICPENDR[3]第三位
GICD->ICPENDR[3] |= (0x1 << 3);
break;
}
//5.清除获取到中断号 EOIR
GICC->EOIR = num;
}