RCC和GPIO初始化函数:
EXTI初始化函数:通用的函数,对KEY1/KEY2/KEY3进行使用
void hal_exti_init(事件编号,GPIOF组对应编号,触发方式)
GIC层初始化函数:通用的函数,对KEY1/KEY2/KEY3进行使用
void hal__GIC_init(中断id,优先级)
实验现象:
当按键1按下之后,1)打印一句话,并且需要打印出中断号 2)LED1灯的状态进行取反
当按键2按下之后,1)打印一句话,并且需要打印出中断号2)LED2灯的状态进行取反
当按键3按下之后,1)打印一句话,并且需要打印出中断号 2)LED3灯的状态进行取反
key_light.h
#ifndef __KEY_LIGHT_H__
#define __KEY_LIGHT_H__
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_exti.h"
#include "stm32mp1xx_gic.h"
//RCC,GPIO初始化
//pf_num:PF组引脚的编号
void rcc_gpio_init(unsigned int pf_num);
//EXTI初始化
//event_num:事件编号
//gpiof_num:GPIOF组对应编号
//type:触发方式 1为下降沿触发
void exti_init(unsigned int event_num,unsigned int gpiof_num,unsigned int type);
//GIC初始化
//id:中断号
//pri:优先级 0-2^5-1
void gic_init(unsigned int id,unsigned int pri);
//灯的初始化
void led_init();
#endif
key_light.c
#include"key_light.h"
//按键初始化
//初始化RCC,GPIO章节//RCC,GPIO初始化
//pf_num:PF组引脚的编号
void rcc_gpio_init(unsigned int pf_num)
{
/******RCC章节初始化******/
//1、GPIOF组控制器使能 MP_AHB4ENSETR[5]=1
RCC->MP_AHB4ENSETR |= (0x1 << 5);
/******GPIO章节初始化******/
//1、将PF(pf_num)引脚设置为输入模式 PF9--->MODER[19:18]=00 PF7--->MODER[15:14]=00 PF8--->MODER[17:16]=00
GPIOF->MODER &= (~(0x3 << (2*pf_num)));
}
//EXTI初始化
//event_num:事件编号
//gpiof_num:GPIOF组对应编号
//type:触发方式 1为下降沿触发,0为上升沿触发
void exti_init(unsigned int event_num,unsigned int gpiof_num,unsigned int type)
{
//event_num%4求商
unsigned int s = event_num / 4;
//event_num%4取余
unsigned int yu = event_num % 4;
//EXTICR1的地址
unsigned int *p = &(EXTI->EXTICR1);
//1、设置中断选择寄存器
*(p+s) &= (~(0xff << (8*yu)));
*(p+s) |= (gpiof_num << (8*yu));
//2、设置事件触发方式
if(type == 1)
//设置事件触发为下降沿
EXTI->FTSR1 |= (0x1 << event_num);
else if(type == 0)
//设置事件触发为下降沿
EXTI->RTSR1 |= (0x1 << event_num);
//3、设置中断不屏蔽
EXTI->C1IMR1 |= (0x1 << event_num);
}
//GIC初始化
//id:中断号
//pri:优先级 0-2^5-2
void gic_init(unsigned int id,unsigned int pri)
{
/******GICD章节初始化******/
//1、设置中断使能寄存器
GICD->ISENABLER[id / 32] |= (0x1 << (id % 32));
//2、设置全局控制
GICD->CTRL |= 0x1;
//3、设置优先级
GICD->IPRIORITYR[id / 4] &= (~(0x1f << ((id % 4)*8+3)));
GICD->IPRIORITYR[id / 4] |= (pri << ((id % 4)*8+3));
//4、设置目标分配寄存器
GICD->ITARGETSR[id / 4] &= (~(0x3 << ((id % 4)*8)));
GICD->ITARGETSR[id / 4] |= (0x1 << ((id % 4)*8));
/******GICC章节初始化******/
//1、设置优先级 PMR[7:3]
GICC->PMR &= (~(0x1f << 3));
GICC->PMR |= (0x1f << 3);
//2、设置中断全局控制器 CTLR[0]=1
GICC->CTRL |= 0x1;
}
//灯的初始化
void led_init()
{
/*****RCC章节*******/
//1、GPIOE,GPIOF使能
RCC->MP_AHB4ENSETR |= (0x1 << 4);
RCC->MP_AHB4ENSETR |= (0x1 << 5);
/*****GPIO章节*******/
//LED1
//1、设置模式为输出模式 MODER[21:20] = 01
GPIOE->MODER &= (~(0x3 << 20));
GPIOE->MODER |= (0x1 << 20);
//2、设置输出类型,推挽模式 OTYPER[10] = 0
GPIOE->OTYPER &= (~(0x1 << 10));
//3、设置输出速度,低速 OSPEEDR[21:20] = 00
GPIOE->OSPEEDR &= (~(0x3 << 20));
//4、不设置上拉下拉电阻 PUPDR[21:20] = 00
GPIOE->PUPDR &= (~(0x3 << 20));
//LED2
//1、设置模式为输出模式 MODER[21:20] = 01
GPIOF->MODER &= (~(0x3 << 20));
GPIOF->MODER |= (0x1 << 20);
//2、设置输出类型,推挽模式 OTYPER[10] = 0
GPIOF->OTYPER &= (~(0x1 << 10));
//3、设置输出速度,低速 OSPEEDR[21:20] = 00
GPIOF->OSPEEDR &= (~(0x3 << 20));
//4、不设置上拉下拉电阻 PUPDR[21:20] = 00
GPIOF->PUPDR &= (~(0x3 << 20));
//LED3
//1、设置模式为输出模式 MODER[17:16] = 01
GPIOE->MODER &= (~(0x3 << 16));
GPIOE->MODER |= (0x1 << 16);
//2、设置输出类型,推挽模式 OTYPER[8] = 0
GPIOE->OTYPER &= (~(0x1 << 8));
//3、设置输出速度,低速 OSPEEDR[17:16] = 00
GPIOE->OSPEEDR &= (~(0x3 << 8));
//4、不设置上拉下拉电阻 PUPDR[17:16] = 00
GPIOE->PUPDR &= (~(0x3 << 8));
}
main.c
#include"key_light.h"
#define KEY1_PF_NUM 9
#define KEY2_PF_NUM 7
#define KEY3_PF_NUM 8
#define KEY1_EVENT_NUM 9
#define KEY2_EVENT_NUM 7
#define KEY3_EVENT_NUM 8
#define GPIOF_NUM 5
#define TYPE_FALLING 1
#define TYPE_RISING 0
#define KEY1_ID 99
#define KEY2_ID 97
#define KEY3_ID 98
#define KEY1_PRI 1
#define KEY2_PRI 2
#define KEY3_PRI 3
int main()
{
//初始化key1
//key1----->PF9----->EXTI9----->99
rcc_gpio_init(KEY1_PF_NUM);
exti_init(KEY1_EVENT_NUM,GPIOF_NUM,TYPE_FALLING);
gic_init(KEY1_ID,KEY1_PRI);
//初始化key2
//key2----->PF7----->EXTI7----->97
rcc_gpio_init(KEY2_PF_NUM);
exti_init(KEY2_EVENT_NUM,GPIOF_NUM,TYPE_FALLING);
gic_init(KEY2_ID,KEY2_PRI);
//初始化key3
//key3----->PF8----->EXTI8----->98
rcc_gpio_init(KEY3_PF_NUM);
exti_init(KEY3_EVENT_NUM,GPIOF_NUM,TYPE_FALLING);
gic_init(KEY3_ID,KEY3_PRI);
//初始化LED1,LED2,LED3
led_init();
while(1)
{
}
return 0;
}
do_irq.c
#include"key_light.h"
extern void printf(const char *fmt, ...);
void do_irq(void)
{
//获取中断号
unsigned int num;
num = (GICC->IAR & (0x3ff));
//判断中断号
switch (num)
{
case 99:
printf("this is key1#####\n");
printf("num = %d\n",num);
//LED1状态取反
GPIOE->ODR ^= (0x1 << 10);
//设置key1清除EXTI层挂起中断标志位 FPR1[9]=1
EXTI->FPR1 |= (0x1 << 9);
//设置key1清除GICD层中断挂起标志位 ICPENDR3[3]=1
GICD->ICPENDR[3] |= (0x1 << 3);
break;
case 97:
printf("this is key2#####\n");
printf("num = %d\n",num);
//LED2状态取反
GPIOF->ODR ^= (0x1 << 10);
//设置key2清除EXTI层挂起中断标志位 FPR1[7]=1
EXTI->FPR1 |= (0x1 << 7);
//设置key2清除GICD层中断挂起标志位 ICPENDR3[1]=1
GICD->ICPENDR[3] |= (0x1 << 1);
break;
case 98:
printf("this is key3#####\n");
printf("num = %d\n",num);
//LED3状态取反
GPIOE->ODR ^= (0x1 << 8);
//设置key3清除EXTI层挂起中断标志位 FPR1[8]=1
EXTI->FPR1 |= (0x1 << 8);
//设置key3清除GICD层中断挂起标志位 ICPENDR3[2]=1
GICD->ICPENDR[3] |= (0x1 << 2);
break;
default:
break;
}
//清除中断号
GICC->EOIR = num;
}