src/key_it.c
cs
1 #include "key_it.h"
2
3 //按键1中断配置
4 void key1_config()
5 {
6 //RCC章节
7 //1:使能gpio f
8 RCC->MP_AHB4ENSETR |= (0x1<<5);
9 //因为exti和gic属于芯片内部 所以无需使能
10
11 //GPIO章节
12 //1:将key1对应的pf9引脚模式设置为输入
13 RCC->MODER &= (~(0x3<<18));
14
15 //EXTI章节
16 //1:设置PF9生成exti9事件
17 //EXTI_EXTICR3:外部中断选择寄存器,选择和哪一个EXTI编号进行连接
18 //EXTI编号 / 4 = 商...余数 9/4=2...1
19 //商+1:表示操作哪一个寄存器 编号3寄存器
20 //余数*8:操作寄存器8位中的最低位 8
21 //每8位管理一个寄存器编号,所以长度为8位->[15:8]
22 //pf9对应值为0x05 [15:8]->0x05
23 EXTI->EXTICR3 &= (~(0xFF<<8));
24 EXTI->EXTICR3 |= (0x05<<8);
25
26 //2:设置下降沿检测EXTI9事件
27 //EXTI_FTSR1:下降沿事件选择寄存器
28 //设置EXTI编号为下降沿触发
29 //每一位检测一个事件 写1使能
30 EXTI->FTSR1 |= (0x1<<9);
31
32 //3:取消exti的事件屏蔽
33 //EXTI_IMR1:中断屏蔽寄存器 设置EXTI层中断是否屏蔽
34 //设置1不屏蔽
35 EXTI->C1IMR1 |= (0x1<<9);
36
37 //4:EXTI_FPR1:下降沿挂起寄存器 清除EXTI层中断挂起标志位
38 //置1清除
39 //EXTI->FPR1 |= (0x1<<9);
40
41 //GIC章节
42 //GICD_CTLR:设置GICD层组0使能
43 GICD->cTRL |= 0x1;
44
45 //GICD_ISENABLERx(0 ~ 8):中断设置使能寄存器
46 //设置对应的中断号使能
47 //GIC层一共管理288个中断号
48 //一个寄存器32位,每一位管理一个中断号,所以一个寄存器最多管理32个中断号
49 //288 / 32 = 9 个中断设置使能寄存器GICD_ISENABLERx(0 ~ 8)
50 //根据中断号,可以直接计算出操作哪一个寄存器,以及寄存器的位数
51 //中断号 / 32 = 商........余数 99/32=3...3
52 //商:表示操作哪一个寄存器 3号寄存器
53 //余数:操作寄存器位数
54 //KEY1==>PF9==>EXTI9编号=>事件9=>99中断号=99/32=3...3=>GICD_ISENABLER3[3]=1
55 GICD->ISENABLER[3] |= (0x1<<3);
56
57 //GICD_IPRIORITYRx(0 ~ 71):中断优先级寄存器
58 //设置GICD层中99号中断优先级
59 //GIC层一共管理288个中断号(16个PPI,16个SGI,256个SPI)
60 //寄存器32位,每八位管理一个中断号,所以一个寄存器最多管理4个中断号
61 //288/4=72个寄存器
62 //中断号 / 4 = 商........余数 99/4=24...3
63 //商:表示操作哪一个寄存器 第24个寄存器
64 //余数*8+3:操作寄存器位数中五位中最低位 27 [31,27](8位空三位)
65 GICD->IPRIORITYR[24] &= (~(0x1F<<27));//设置为0 数值越小表示优先级越高
66
67 //GICD_ITARGETSRx(0 ~ 71):中断目标分配寄存器 设置GICD层中断分配给哪一个cpu
68 //288个中断号
69 //寄存器32位,每八位管理一个中断号,所以一个寄存器最多管理4个中断号
70 //288/4=72 个中断优先级寄存器GICD_ITARGETSRx(0 ~ 71)
71 //中断号 / 4 = 商........余数 99/4=26...3
72 //商:表示操作哪一个寄存器 26
73 //余数*8:操作寄存器位数中五位中最低位 24 [25,24] 6位置空
74 GICD->ITARGETSR[26] &= (~(0x3<<24));
75 GICD->ITARGETSR[26] |= (0x1<<24); // 0b01 =====> 分配给cpu0
76
77 //GICD_ICPENDRx(0 ~ 8):清除GICD层中断挂起标志位
78 //288个中断号,寄存器32位每一位管理一个中断号,一个寄存器最多管理32个中断号
79 //288 / 32 = 9
80 //中断号 / 32 = 商........余数 99/32=3...3
81 //商:表示操作哪一个寄存器 3
82 //余数:操作寄存器位数 3
83 //GICD->ICPENDR[3] |= (0x1<<3);
84
85 //GICC_CTLR:设置GICC层组0使能
86 //GICC_CTLR[0] = 1 =======> 设置GICC层组0使能
87 GICC->CTLR |= 0x1;
88
89 //GICC_PMR:GICC层中断优先级屏蔽寄存器
90 //GICC_PMR[7:3] = 设置优先级值
91 //1)GICD层的优先级需要比GICC层优先级高
92 // 2)数值越小表示优先级越高
93 GICC->PMR |= (0x1F<<3);
94 }
~
include/key_it.h
cs
1 #ifndef wwe
2 #define wwe
3
4 #include "stm32mp1xx_gpio.h"
5 #include "stm32mp1xx_rcc.h"
6 #include "stm32mp1xx_exti.h"
7 #include "stm32mp1xx_gic.h"
8
9 void key1_config();
10 void key2_config();
11 void key3_config();
12
13 #endif
do.c
cs
1 #include "key_it.h"
2 //中断处理函数
3 extern void printf(const char *fmt,...);
4 void do_irp(void)
5 {
6 //先获取中断号
7 //GICC_IAR:获取中断号的值 将GICC_IAR[9:0]的值读出来
8 unsigned int irpno=(GICC->IAR &= (~(0x3FF)));
9 switch(irpno)
10 {
11 case 99://key1中断
12 //中断处理
13 printf("key1触发\n");
14 //清除gicd中的中断排队标志
15 //GICD_ICPENDRx(0 ~ 8):清除GICD层中断挂起标志位
16 //288个中断号,寄存器32位每一位管理一个中断号,一个寄存器最多管理32个中断号
17 //288 / 32 = 9
18 //中断号 / 32 = 商........余数 99/32=3...3
19 //商:表示操作哪一个寄存器 3
20 //余数:操作寄存器位数 3
21 GICD->ICPENDR[3] |= (0x1<<3);
22 //清除exit中的事件挂起标志
23 //EXTI_FPR1:下降沿挂起寄存器 清除EXTI层中断挂起标志位
24 //置1清除
25 EXTI->FPR1 |= (0x1<<9);
26 break;
27
28 }
29 //清除iar保存的中断号
30 //GICC_EOIR:GICC end of interrupt register 寄存器作用:清除中断号
31 //将获取到的中断号(IAR)进行清除
32 GICC->EOIR = irqno;
33 }
main.c
cs
1 #include "key_it.h"
2 extern void printf(const char *fmt,...);
3
4 //封装延时函数
5 void delay(int ms)
6 {
7 int i,j;
8 for(i=0,i<ms,i++)
9 {
10 for(j=0,j<2000,j++)
11 {}
12 }
13 }
14 int main()
15 {
16 key1_config();
17 while(1)
18 {
19 printf("main.c\n");
20 delay(1000);
21
22
23 }
24 return 0;
25 }