led_key.h
#ifndef __KEY_H__
#define __KEY_H__
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_exti.h"
#include "stm32mp1xx_gic.h"
void hal_rcc_gpio_init();
void hal_exti_init(unsigned int event_num, unsigned int gpiof_num, int status);
void hal_gic_init(unsigned int id, int priority);
#endif
led_key.c
#include "key.h"
//KEY1------>PF9
//KEY2------>PF7
//KEY3------>PF8
//LED1------>PE10
//LED2------>PF10
//LED3------>PE8
void hal_rcc_gpio_init()
{
//RCC章节初始化
//设置GPIOF、GPIOE组使能
RCC->MP_AHB4ENSETR |= (0x3<<4);
//GPIO章节初始化
//1、设置PF9,PF8,PF7引脚为输入模式
GPIOF->MODER &= (~(0x3<<18));
GPIOF->MODER &= (~(0x3<<14));
GPIOF->MODER &= (~(0x3<<16));
//2、设置PE10,PF10,PE8引脚相关内容
//PE10
GPIOE->MODER &= (~(0X3<<20));
GPIOE->MODER |= (0X1<<20);
GPIOE->OTYPER &=(~(0X1<<10));
GPIOE->OSPEEDR &= (~(0X3<<20));
GPIOE->PUPDR &= (~(0X3<<20));
//PF10
GPIOF->MODER &= (~(0X3<<20));
GPIOF->MODER |= (0X1<<20);
GPIOF->OTYPER &=(~(0X1<<10));
GPIOF->OSPEEDR &= (~(0X3<<20));
GPIOF->PUPDR &= (~(0X3<<20));
//PE8
GPIOE->MODER &= (~(0X3<<16));
GPIOE->MODER |= (0X1<<16);
GPIOE->OTYPER &=(~(0X1<<8));
GPIOE->OSPEEDR &= (~(0X3<<16));
GPIOE->PUPDR &= (~(0X3<<16));
}
void hal_exti_init(unsigned int event_num, unsigned int gpiof_num, int status)
{
int x = (event_num / 4) + 1; //要操作的寄存器
int y = (event_num % 4) * 8; //要操作的寄存器8位中的最低位
//EXTI章节初始化
//1、设置EXTI中断选择
switch (x){
case 1:
EXTI->EXTICR1 &= (~(0xff<<y));
EXTI->EXTICR1 |= (gpiof_num<<y);
break;
case 2:
EXTI->EXTICR2 &= (~(0xff<<y));
EXTI->EXTICR2 |= (gpiof_num<<y);
break;
case 3:
EXTI->EXTICR3 &= (~(0xff<<y));
EXTI->EXTICR3 |= (gpiof_num<<y);
break;
case 4:
EXTI->EXTICR4 &= (~(0xff<<y));
EXTI->EXTICR4 |= (gpiof_num<<y);
break;
}
//2、设置EXTI下降沿触发方式
EXTI->FTSR1 |= (status<<event_num);
//3、设置EXTI中断不屏蔽
EXTI->C1IMR1 |= (0x1<<event_num);
}
//GIC章节初始化
void hal_gic_init(unsigned int id, int priority)
{
//GICD章节初始化
//1、中断设置使能寄存器
int x = id / 32; //操作的哪个寄存器
int y = id % 32; //操作的最低位数
GICD->ISENABLER[x] |= (0x1<<y);
//2、设置中断优先级寄存器
int m = id / 4; //操作的哪个寄存器
int n = ((id % 4)*8)+3; //操作的最低位
GICD->IPRIORITYR[m] &= (~(0x1f<<n));
//3、设置中断目标分配寄存器
int p = id / 4; //操作的哪个寄存器
int q = (id % 4)*8; //操作的最低位
GICD->ITARGETSR[p] &= (~(0x3<<q));
GICD->ITARGETSR[p] |= (0x1<<q);
//4、设置全局控制寄存器
GICD->CTRL |= (0x1<<0);
//GICC章节初始化
//1、设置中断优先级寄存器
GICC->PMR &= (~(0x1f<<3));
GICC->PMR |= (priority<<3);
//2、设置全局控制寄存器
//GICC_CTLR[0] = 1
GICC->CTRL |= (0x1<<0);
}
do_irq.c
#include "key.h"
extern void delay_ms(int ms);
extern void printf(const char *fmt, ...);
unsigned int num = 0;
void do_irq(void)
{
//1、获取中断号
//num = GICC_IAR[9:0]
num = (GICC->IAR & (0x3ff));
//2、判断中断号
if(num == 99)
{
delay_ms(500);
printf("按键1按下!\n");
printf("num = %d\n",num);
//LED1状态取反
GPIOE->ODR ^= (0x1<<10);
//3、清除EXTI层中断挂起标志位
//KEY1 EXTI_FPR1[9] = 1
EXTI->FPR1 |= (0x1<<9);
//4、清除GICD层中断挂起标志位
//KEY1 GICD_ICPENDR3[3] = 1
GICD->ICPENDR[3] |= (0x1<<3);
}else if(num == 97)
{
delay_ms(500);
printf("按键2按下!\n");
printf("num = %d\n",num);
//LED2状态取反
GPIOF->ODR ^= (0x1<<10);
//3、清除EXTI层中断挂起标志位
//KEY2 EXTI_FPR1[7] = 1
EXTI->FPR1 |= (0x1<<7);
//4、清除GICD层中断挂起标志位
//KEY2 GICD_ICPENDR3[1] = 1
GICD->ICPENDR[3] |= (0x1<<1);
}else if(num == 98)
{
delay_ms(500);
printf("按键3按下!\n");
printf("num = %d\n",num);
//LED3状态取反
GPIOE->ODR ^= (0x1<<8);
//3、清除EXTI层中断挂起标志位
//KEY3 EXTI_FPR1[8] = 1
EXTI->FPR1 |= (0x1<<8);
//4、清除GICD层中断挂起标志位
//KEY3 GICD_ICPENDR3[2] = 1
GICD->ICPENDR[3] |= (0x1<<2);
}
//5、清除GICC层中断挂起标志位
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++);
}
int main(int argc, const char *argv[])
{
hal_rcc_gpio_init();
//KEY1
hal_exti_init(9, 0x05, 0x1);
hal_gic_init(99, 0x1f);
//KEY2
hal_exti_init(7, 0x05, 0x1);
hal_gic_init(97, 0x1f);
//KEY3
hal_exti_init(8, 0x05, 0x1);
hal_gic_init(98, 0x1f);
while(1)
{
}
return 0;
}
实验现象