一、实验原理分析
实验板:stm32mp157a-fsmp1a
本次中断是检测按键的下降沿信号,接收到信号进入异常处理,进行相应的异常处理流程
二、电路分析
分析三个按键对应的GPIO接口:
KEY1----->PF9
KEY2----->PF7
KEY3----->PF8
三、框图分析
由上图可知需要分析芯片手册四个章节
RCC章节:使能GPIO控制器
GPIO章节:设置引脚为输入模式
EXTI章节:检测中断的触发方式
GIC章节:设置GPIOF引脚对应的中断号
四、工作流程图
流程分解:
1,按键按下
2,GPIO输入(MODER)
3,EXT检测中断触发
3.1 中断选择(EXTI_EXTICR3)功能:GPIO控制器和EXTI控制器进行连接
3.2 事件检测(下降沿)(EXTI_FTSR1)
3.3 事件屏蔽(不屏蔽)(EXTI_IMR1)
3.4 清除中断挂起标志位(EXTI_FPR1)
4,GIC设置GPIOF引脚对应的中断号
4.1 GICD层:分配器层
4.1.1 使能GICD层(GICD_CTLR)
4.1.2 中断设置使能 GICD_ISENABLERx
4.1.3 中断优先级设置 GICD_IPRIORITYRx(数字越低优先级越高)
4.1.4 选择CPU(GICD_ITARGETSRx)
4.1.5 清除中断挂起标志位 GICD_ICPENDRx
4.2 GICC层:CPU接口层
4.2.1 使能GICC层 (GICC_CTLR)
4.2.2 优先级设置 (GICC_PMR)需要比GICD层设计的中断优先级的值要大
4.2.3 获取中断号 GICC_IAR
4.2.4 清除按键中断号 GICC_EOIR
五、代码实现
按键按下,打印按键信息
key.h
#ifndef __KEY5_H__
#define __KEY5_H__
#include "./stm32mp1xx_exti.h"
#include "./stm32mp1xx_gpio.h"
#include "./stm32mp1xx_rcc.h"
#include "./stm32mp1xx_gic.h"
//初始化EITI层
void pf9_exti_init();
//初始化GICD层
void pf9_gicd_init();
//初始化GICC层
void pf9_dicc_init();
//初始化GPIO层
void gpio_init();
#endif
key.c
#include "key5.h"
//初始化gpio层
void gpio_init()
{
//rcc使能GPIOF寄存器
RCC->MP_AHB4ENSETR |= (0X1 << 5);
RCC->MP_AHB4ENSETR |= (0X1 << 4);
/*****设置GPIOF系列寄存器****/
//设置GPIOE 8,10,GPIOF 10为输出模式
GPIOE->MODER &= (~(0x3 <<16));
GPIOE->MODER |= (0X1<<16);
GPIOE->MODER &= (~(0x3 <<20));
GPIOE->MODER |= (0x1 <<20);
GPIOF->MODER &= (~(0x3 <<20));
GPIOF->MODER |= (0x1 <<20);
//设置GPIOF,7,8,9模式为输入模式
GPIOF->MODER &= (~(0X3 << 18));
GPIOF->MODER &= (~(0X3 << 16));
GPIOF->MODER &= (~(0X3 << 14));
//设置GPIOE 8,10,GPIOF 10的输出类型
GPIOE->OTYPER &= (~(0x1 <<8));
GPIOE->OTYPER &= (~(0x1 <<10));
GPIOF->OTYPER &= (~(0x1 <<10));
//设置GPIOE 8,10,GPIOF 10的输出速度
GPIOE->OSPEEDR &= (~(0X3 <<16));
GPIOE->OSPEEDR &= (~(0X3 <<20));
GPIOF->OSPEEDR &= (~(0X3 <<20));
//设置GPIOE 8,10,GPIOF 10上下拉
GPIOE->PUPDR &= (~(0X3 <<16));
GPIOE->PUPDR &= (~(0X3 <<20));
GPIOF->PUPDR &= (~(0X3 <<20));
}
//初始化EITI层
void pf9_exti_init()
{
/****设置EXTI系列寄存器*****/
//1.中断寄存器与GPIO连接
EXTI->EXTICR3 &= (~(0xff << 8));
EXTI->EXTICR3 |= (0X05 << 8);
EXTI->EXTICR3 &= (~(0xff << 0));
EXTI->EXTICR3 |= (0X05 << 0);
EXTI->EXTICR2 &= (~(0xff << 24));
EXTI->EXTICR2 |= (0X05 << 24);
//2.检测事件为下降沿
EXTI->FTSR1 |= (0X1 <<7);
EXTI->FTSR1 |= (0X1 <<8);
EXTI->FTSR1 |= (0X1 <<9);
//3.设置中断屏蔽寄存器为不屏蔽
EXTI->C1IMR1 |= (0X1 <<7);
EXTI->C1IMR1 |= (0X1 <<8);
EXTI->C1IMR1 |= (0X1 <<9);
}
//初始化GICD层
void pf9_gicd_init()
{
/*****设置GICD系列寄存器*****/
//使能GICD(全局)
GICD->CTRL |= (0X1 <<0);
//中断设置使能(对应中断号)
GICD->ISENABLER[3] |= (0X1 <<3);
GICD->ISENABLER[3] |= (0X1 <<1);
GICD->ISENABLER[3] |= (0X1 <<2);
//中断优先级设置
GICD->IPRIORITYR[24] &= (~(0X1F <<11));
GICD->IPRIORITYR[24] |= (0X1 <<11);
GICD->IPRIORITYR[24] &= (~(0X1F <<19));
GICD->IPRIORITYR[24] |= (0X1 <<19);
GICD->IPRIORITYR[24] &= (~(0X1F <<27));
GICD->IPRIORITYR[24] |= (0X1 <<27);
//选择CPU,0号,设置中断目标分配
GICD->ITARGETSR[24] &= (~(0X3 <<8));
GICD->ITARGETSR[24] |= (0X1 <<8);
GICD->ITARGETSR[24] &= (~(0X3 <<16));
GICD->ITARGETSR[24] |= (0X1 <<16);
GICD->ITARGETSR[24] &= (~(0X3 <<24));
GICD->ITARGETSR[24] |= (0X1 <<24);
}
//初始化GICC层
void pf9_dicc_init()
{
/*****设置GICC系列寄存器*****/
//使能GICC
GICC->CTRL |= (0X1 <<0);
//输入中断优先级
GICC->PMR &= (~(0X1F <<3));
GICC->PMR |= (0XF <<3);
}
main.c
#include "key5.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()
{
//调用初始化函数
gpio_init();
pf9_exti_init();
pf9_gicd_init();
pf9_dicc_init();
while(1)
{
}
return 0;
}
do_irq.c(异常处理函数)
#include "key5.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;
//获取中断号
num=GICC->IAR & 0X1FF;
switch(num)
{
case 97:
{
delay_ms(500);
printf("key2######\n");
//清除EXTI层挂起标志位
EXTI->FPR1 |= (0x1 <<7);
EXTI->FPR1 |= (0x1 <<8);
EXTI->FPR1 |= (0x1 <<9);
//清除GICD层挂起标志位
GICD->ICPENDR[3] |= (0X1 <<3);
GICD->ICPENDR[3] |= (0X1 <<1);
GICD->ICPENDR[3] |= (0X1 <<2);
}
break;
case 98:
{
delay_ms(500);
printf("key3######\n");
//清除EXTI层挂起标志位
EXTI->FPR1 |= (0x1 <<7);
EXTI->FPR1 |= (0x1 <<8);
EXTI->FPR1 |= (0x1 <<9);
//清除GICD层挂起标志位
GICD->ICPENDR[3] |= (0X1 <<3);
GICD->ICPENDR[3] |= (0X1 <<1);
GICD->ICPENDR[3] |= (0X1 <<2);
}
break;
case 99:
{
delay_ms(500);
printf("key1######\n");
//清除EXTI层挂起标志位
EXTI->FPR1 |= (0x1 <<7);
EXTI->FPR1 |= (0x1 <<8);
EXTI->FPR1 |= (0x1 <<9);
//清除GICD层挂起标志位
GICD->ICPENDR[3] |= (0X1 <<3);
GICD->ICPENDR[3] |= (0X1 <<1);
GICD->ICPENDR[3] |= (0X1 <<2);
}
break;
}
//清除中断号
GICC->EOIR &= (~(0X1FF));
GICC->EOIR |= num;
}
实验现象: