创作本文目的:记录自己的学习历程
一、A7实现按键中断的步骤
1.分析硬件
三个按键对应的GPIO接口
KEY1----->PF9
KEY2----->PF7
KEY3----->PF8
2.分析芯片手册
RCC章节:设置寄存器时钟使能
GPIOF章节:设置引脚为输入模式
MODER
EXTI章节:检测中断的触发方式
EXTI_EXTICR3 --- 选择GPIO控制器和EXTI控制器进行连接
EXTI_FTSR1 --- 事件检测(下降沿)
EXTI_IMR1 --- 事件屏蔽(不屏蔽)
EXTI_FPR1 --- 清除中断挂起标志位
GIC章节:设置GPIO组引脚对应的中断号
GICD:
GICD_CTLR --- 使能GICD层
GICD_ISENABLERx --- 中断设置使能
GICD_IPRIORITYRx --- 中断优先级设置(数字越低优先级越高)
GICD_ITARGETSRx --- 选择CPU
GICD_ICPENDRx --- 清除中断挂起标志位
GICC:
GICC_CTLR --- 使能GICC层
GICC_PMR --- 优先级设置(需要比GICD层设计的中断优先级的值要大)
GICC_IAR --- 获取中断号
GICC_EOIR --- 清除按键中断号
3.代码
.h
#ifndef __KEY_H__
#define __KEY_H__
#include "stm32mp1xx_exti.h"
#include "stm32mp1xx_gic.h"
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_gpio.h"
//总初始化
void init();
//key1初始化
void pf9_init();
//key2初始化
void pf7_init();
//key3初始化
void pf8_init();
#endif
.c
#include "key.h"
//总初始化
void init()
{
/*RCC章节初始化*/
//1.设置GPIOF组时钟使能
RCC->MP_AHB4ENSETR |= (0x1 << 5);
/*GPIO章节初始化*/
//1.设置PF9,PF7,PF8引脚为输入模式
GPIOF->MODER &= (~(0x3 << 18));
GPIOF->MODER &= (~(0x3 << 14));
GPIOF->MODER &= (~(0x3 << 16));
/*EXTI章节初始化*/
//1.1设置PF9引脚和EXTI9控制器进行连接
EXTI->EXTICR3 &= (~(0xff << 8));
EXTI->EXTICR3 |= (0x05 << 8);
//1.2设置PF7引脚和EXTI7控制器进行连接
EXTI->EXTICR2 &= (~(0xff << 24));
EXTI->EXTICR2 |= (0x05 << 24);
//1.3设置PF8引脚和EXTI8控制器进行连接
EXTI->EXTICR3 &= (~(0xff << 0));
EXTI->EXTICR3 |= (0x05 << 0);
//2.设置PF9,PF7,PF8引脚检测方式下降沿
EXTI->FTSR1 |= (0x7 << 7);
//3.设置PF9,PF7,PF9引脚中断不屏蔽
EXTI->C1IMR1 |= (0x7 << 7);
//初始化GICD层
//1.设置GICD层全局中断使能寄存器
GICD->CTRL |= (0x1 << 0);
//2.设置GICD层中断使能寄存器
GICD->ISENABLER[3] |= (0x7 << 1);
//3.设置GICD层中断优先级寄存器
GICD->IPRIORITYR[24] &= (~(0x1f << 27));
GICD->IPRIORITYR[24] |= (0x18 << 27);
GICD->IPRIORITYR[24] &= (~(0x1f << 11));
GICD->IPRIORITYR[24] |= (0x18 << 11);
GICD->IPRIORITYR[24] &= (~(0x1f << 19));
GICD->IPRIORITYR[24] |= (0x18 << 19);
//4.设置GICD层中断目标分配寄存器
GICD->ITARGETSR[24] &= (~(0x3 << 24));
GICD->ITARGETSR[24] |= (0x01 << 24);
GICD->ITARGETSR[24] &= (~(0x3 << 8));
GICD->ITARGETSR[24] |= (0x01 << 8);
GICD->ITARGETSR[24] &= (~(0x3 << 16));
GICD->ITARGETSR[24] |= (0x01 << 16);
//初始化GICC层
//1.设置GICC层全局中断使能寄存器
GICC->CTRL |= (0x1 << 0);
//2.设置GICC层中断优先级寄存器
GICC->PMR &= (~(0x1f << 3));
GICC->PMR |= (0x1f << 3);
}
/*key1---PF9*/
//初始化
void pf9_init()
{
/*RCC章节初始化*/
//1.设置GPIOF组时钟使能
RCC->MP_AHB4ENSETR |= (0x1 << 5);
/*GPIO章节初始化*/
//1.设置PF9,PF7,PF8引脚为输入模式
GPIOF->MODER &= (~(0x3 << 18));
/*EXTI章节初始化*/
//1.1设置PF9引脚和EXTI9控制器进行连接
EXTI->EXTICR3 &= (~(0xff << 8));
EXTI->EXTICR3 |= (0x05 << 8);
//2.设置PF9,PF7,PF8引脚检测方式下降沿
EXTI->FTSR1 |= (0x1 << 9);
//3.设置PF9,PF7,PF9引脚中断不屏蔽
EXTI->C1IMR1 |= (0x1 << 9);
//1.设置GICD层全局中断使能寄存器
GICD->CTRL |= (0x1 << 0);
//2.设置GICD层中断使能寄存器
GICD->ISENABLER[3] |= (0x1 << 3);
//3.设置GICD层中断优先级寄存器
GICD->IPRIORITYR[24] &= (~(0x1f << 27));
GICD->IPRIORITYR[24] |= (0x18 << 27);
//4.设置GICD层中断目标分配寄存器
GICD->ITARGETSR[24] &= (~(0x3 << 24));
GICD->ITARGETSR[24] |= (0x01 << 24);
//1.设置GICC层全局中断使能寄存器
GICC->CTRL |= (0x1 << 0);
//2.设置GICC层中断优先级寄存器
GICC->PMR &= (~(0x1f << 3));
GICC->PMR |= (0x1f << 3);
}
/*key2---PF7*/
//初始化
void pf7_init()
{
/*RCC章节初始化*/
//1.设置GPIOF组时钟使能
RCC->MP_AHB4ENSETR |= (0x1 << 5);
/*GPIO章节初始化*/
//1.设置PF9,PF7,PF8引脚为输入模式
GPIOF->MODER &= (~(0x3 << 14));
/*EXTI章节初始化*/
//1.2设置PF7引脚和EXTI7控制器进行连接
EXTI->EXTICR2 &= (~(0xff << 24));
EXTI->EXTICR2 |= (0x05 << 24);
//2.设置PF9,PF7,PF8引脚检测方式下降沿
EXTI->FTSR1 |= (0x1 << 7);
//3.设置PF9,PF7,PF9引脚中断不屏蔽
EXTI->C1IMR1 |= (0x1 << 7);
/*GICD章节初始化*/
//1.设置GICD层全局中断使能寄存器
GICD->CTRL |= (0x1 << 0);
//2.设置GICD层中断使能寄存器
GICD->ISENABLER[3] |= (0x1 << 1);
//3.设置GICD层中断优先级寄存器
GICD->IPRIORITYR[24] &= (~(0x1f << 11));
GICD->IPRIORITYR[24] |= (0x18 << 11);
//4.设置GICD层中断目标分配寄存器
GICD->ITARGETSR[24] &= (~(0x3 << 8));
GICD->ITARGETSR[24] |= (0x01 << 8);
/*GICC章节初始化*/
//1.设置GICC层全局中断使能寄存器
GICC->CTRL |= (0x1 << 0);
//2.设置GICC层中断优先级寄存器
GICC->PMR &= (~(0x1f << 3));
GICC->PMR |= (0x1f << 3);
}
/*key3---PF8*/
//初始化
void pf8_init()
{
/*RCC章节初始化*/
//1.设置GPIOF组时钟使能
RCC->MP_AHB4ENSETR |= (0x1 << 5);
/*GPIO章节初始化*/
//1.设置PF8引脚为输入模式
GPIOF->MODER &= (~(0x3 << 16));
/*EXTI章节初始化*/
//1.2设置PF8引脚和EXTI8控制器进行连接
EXTI->EXTICR3 &= (~(0xff << 0));
EXTI->EXTICR3 |= (0x05 << 0);
//2.设置PF8引脚检测方式下降沿
EXTI->FTSR1 |= (0x1 << 8);
//3.设置PF8引脚中断不屏蔽
EXTI->C1IMR1 |= (0x1 << 8);
/*GICD章节初始化*/
//1.设置GICD层全局中断使能寄存器
GICD->CTRL |= (0x1 << 0);
//2.设置GICD层中断使能寄存器
GICD->ISENABLER[3] |= (0x1 << 2);
//3.设置GICD层中断优先级寄存器
GICD->IPRIORITYR[24] &= (~(0x1f << 19));
GICD->IPRIORITYR[24] |= (0x18 << 19);
//4.设置GICD层中断目标分配寄存器
GICD->ITARGETSR[24] &= (~(0x3 << 16));
GICD->ITARGETSR[24] |= (0x01 << 16);
/*GICC章节初始化*/
//1.设置GICC层全局中断使能寄存器
GICC->CTRL |= (0x1 << 0);
//2.设置GICC层中断优先级寄存器
GICC->PMR &= (~(0x1f << 3));
GICC->PMR |= (0x1f << 3);
}
do_irq.c(异常处理函数)
include "key.h"
#include "gpio.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;
//LED起始化
RCC_AHB4_ENSETR |= (0x3 << 4);
gpio_init_t init = {OUTPUT,PUSH_PULL,LOW,NO_PUPD};
hal_gpio_init(GPIOE,&init,GPIO_PIN_10);
hal_gpio_init(GPIOF,&init,GPIO_PIN_10);
hal_gpio_init(GPIOE,&init,GPIO_PIN_8);
//获取中断号
num = GICC->IAR & (0x3ff);
switch(num)
{
case 97:
{
delay_ms(500);
printf("key2!!!\n");
hal_gpio_write(GPIOE,GPIO_PIN_10,GPIO_SET);
//清除EXTI层中断挂起标志位
EXTI->FPR1 |= (0x1 << 7);
//清除GICD层中断挂起标志位
GICD->ICPENDR[3] |= (0x1 << 2);
}break;
case 98:
{
delay_ms(500);
printf("key3!!!\n");
hal_gpio_write(GPIOE,GPIO_PIN_10,GPIO_RESET);
//清除EXTI层中断挂起标志位
EXTI->FPR1 |= (0x1 << 8);
//清除GICD层中断挂起标志位
GICD->ICPENDR[3] |= (0x1 << 1);
}break;
case 99:
{
delay_ms(500);
printf("key1!!!\n");
//清除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++);
}
}
int main()
{
init();
/*
//1.pf9初始化
pf9_init();
//3.pf8初始化
pf8_init();
//2.pf7初始化
pf7_init();
*/
while(1)
{
}
return 0;
}
4.效果
按键按下,打印按键信息