1.实验目的:实现KEY1/LEY2/KE3三个按键,中断触发打印一句话,并且灯的状态取反;
key1 ----> LED3灯状态取反;
key2 ----> LED2灯状态取反;
key3 ----> LED1灯状态取反;
2.分析框图:
3.代码:
---key.h头文件---
#ifndef __KEY_H__
#define __KEY_H__
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_gic.h"
#include "stm32mp1xx_exti.h"
typedef enum
{
DISTRIGGER,
ENTRIGGER //下降沿触发方式
}trigger_t;
//KEY1->PF9
//RCC,GPIO,EXTI章节初始化
void hal_exti_pf9_init();
//GIC章节初始化
void hal_gic_pf9_init();
//EXTI初始化函数
//EXTI编号 GPIO组号 触发方式
void hal_exti_init(unsigned int extix,unsigned int groupx,trigger_t trix);
//GIC初始化函数
//中断号,中断优先级
void hal_gic_init(unsigned int interruptx,unsigned int priority);
//led初始化函数
void led_init(gpio_t* gpiox,unsigned int pin);
//led灯开关函数
void led_on_off(gpio_t* gpiox,unsigned int pin,unsigned int status);
#endif
---key.c函数实现---
#include "key.h"
//RCC,GPIO,EXTI章节初始化
void hal_exti_pf9_init()
{
//RCC章节初始化 PF9 [5]=1
RCC->MP_AHB4ENSETR |= (0x1 << 5);
//GPIO章节初始化 [19:18]=00 输入模式
GPIOF->MODER &= (~(0x3 << 18));
//EXTI章节初始化,引脚信号与EXTI连接
//1.EXIT_EXTICR3 EXTI9[15:8]=0x05 0101
EXTI->EXTICR[2] &= (~(0xff << 8));
EXTI->EXTICR[2] |= (0x05 << 8);
//2.EXTI_FTSR1 设置下降沿触发方式 [9]=1
EXTI->FTSR1 |= (0x1 << 9);
//3.EXTI_IMR1 设置中断不屏蔽 [9]=1
EXTI->C1IMR1 |= (0x1 << 9);
}
//GIC章节初始化
void hal_gic_pf9_init()
{
//GICD初始化
//1.GICD_CTRL 使能组0 [0]=1
GICD->CTRL |= (0x1 << 0);
//2.GICD_ISENABLER3 设置GICD层中断使能 3[3]=1
GICD->ISENABLER[3] |= (0x1 << 3);
//3.GICD_IPRIORITYR24 设置中断优先级
//[31:27] = 0b00000
GICD->IPRIORITYR[24] &= (~(0x1f << 27));
//4.GICD_ITARGETSR24 设置中断目标分配给CPU0
//[25:24] = 0b01
GICD->ITARGETSR[24] &= (~(0x3 << 24));
GICD->ITARGETSR[24] |= (0x1 << 24);
//GICD_ICPENDRx 清除GICD层中断挂起标志位
//GICC初始化
//1.GICC_CTRL 设置GICC层组0使能 [0]=1
GICC->CTRL |= (0x1 << 0);
//2.GICC_PMR 设置GICC层中断优先级 [7:3]=0b11111
GICC->PMR |= (0x1f << 3);
}
//EXTI初始化函数
//EXTI编号 GPIO组号 触发方式
void hal_exti_init(unsigned int extix,unsigned int groupx,trigger_t trix)
{
//GPIO章节初始化 输入模式
GPIOF->MODER &= (~(0x3 << 2*extix));
//EXTI章节初始化,引脚信号与EXTI连接
//1.EXIT_EXTICRn EXTI9[]=0x05 0101
EXTI->EXTICR[extix/4] &= (~(0xff << ((extix%4)*8)));
EXTI->EXTICR[extix/4] |= (0x05 << ((extix%4)*8));
//2.EXTI_FTSR1 设置下降沿触发方式
EXTI->FTSR1 |= (trix << extix);
//3.EXTI_IMR1 设置中断不屏蔽 [9]=1
EXTI->C1IMR1 |= (0x1 << extix);
}
//GIC初始化函数
//中断号,中断优先级
void hal_gic_init(unsigned int interruptx,unsigned int priority)
{
//GICD初始化
//1.GICD_CTRL 使能组0 [0]=1
GICD->CTRL |= (0x1 << 0);
//2.GICD_ISENABLER3 设置GICD层中断使能
GICD->ISENABLER[interruptx/32] |= (0x1 << (interruptx%32));
//3.GICD_IPRIORITYR24 设置中断优先级
GICD->IPRIORITYR[interruptx/4] &= (~(priority << ((interruptx%4)*8+3)));
//4.GICD_ITARGETSR24 设置中断目标分配给CPU0
GICD->ITARGETSR[interruptx/4] &= (~(0x3 << (interruptx%4)*8));
GICD->ITARGETSR[interruptx/4] |= (0x1 << (interruptx%4)*8);
//GICC初始化
//1.GICC_CTRL 设置GICC层组0使能 [0]=1
GICC->CTRL |= (0x1 << 0);
//2.GICC_PMR 设置GICC层中断优先级 [7:3]=0b11111
GICC->PMR |= ((priority+1) << 3);
}
//函数功能:GPIO引脚初始化
//参数1:GPIO组号
//参数2:引脚编号
void led_init(gpio_t* gpiox,unsigned int pin)
{
//使能PE10 PF10 PE8
RCC->MP_AHB4ENSETR |= (0x3 << 4);
//1输出模式
gpiox->MODER &= ~(0x3 << (pin*2));
gpiox->MODER |= (0x1 << (pin*2));
//2输出类型
gpiox->OTYPER &= (~(0x1 << pin));
//3输出速率
gpiox->OSPEEDR &= ~(0x3 << (pin*2));
//4拉电阻
gpiox->PUPDR &= ~(0x3 << (pin*2));
}
//函数功能:GPIO引脚操作 1 点亮,0 熄灭
//参数1:GPIO组号
//参数2:引脚编号
//参数3:写内容
void led_on_off(gpio_t* gpiox,unsigned int pin,unsigned int status)
{
if(status == 0) //熄灭
{
gpiox->ODR &= ~(0x1 << pin);
}else
{
gpiox->ODR |= (0x1 << pin);
}
}
---do_irq.c终端处理函数---
#include "key.h"
extern void printf(const char *fmt, ...);
int flag1=0;
int flag2=0;
int flag3=0;
//中断处理函数
void do_irq(void)
{
//1获取中断号 IAR[9:0]
unsigned int num = 0;
num = GICC->IAR & 0x3ff;
//2判断中断号,并且打印一句话
switch(num)
{
case 99:
printf("KEY1按键中断\n");
//led3灯状态取反
if(flag1%2 == 0)
led_on_off(GPIOE,8,1);
else
led_on_off(GPIOE,8,0);
//3清楚EXTI层中断挂起标志位 [9]=1
//EXTI_FDR1 [9]=1
EXTI->FPR1 |= (0x1 << 9);
//4清楚GICD层中断挂起标志位
//GICD_ICPENDR3 [3]=1
GICD->ICPENDR[3] |= (0x1 << 3);
flag1++;
break;
case 97:
printf("KEY2按键中断\n");
//led2灯状态取反
if(flag2%2 == 0)
led_on_off(GPIOF,10,1);
else
led_on_off(GPIOF,10,0);
EXTI->FPR1 |= (0x1 << 7);
GICD->ICPENDR[3] |= (0x1 << 1);
flag2++;
break;
case 98:
printf("KEY3按键中断\n");
//led1灯状态取反
if(flag3%2 == 0)
led_on_off(GPIOE,10,1);
else
led_on_off(GPIOE,10,0);
EXTI->FPR1 |= (0x1 << 8);
GICD->ICPENDR[3] |= (0x1 << 2);
flag3++;
break;
}
//5清楚获取到的中断号
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()
{
//pf9初始化
hal_exti_pf9_init();
hal_gic_pf9_init();
//EXTI初始化函数
hal_exti_init(7,0x05,ENTRIGGER);
hal_exti_init(8,0x05,ENTRIGGER);
//GIC初始化函数
hal_gic_init(97,1);
hal_gic_init(98,1);
//led初始化函数
led_init(GPIOE,10);
led_init(GPIOF,10);
led_init(GPIOE,8);
while(1)
{
}
return 0;
}
4.实验现象: