一、分析电路图
分析三个按键对应的GPIO接口:
KEY1----->PF9
KEY2----->PF7
KEY3----->PF8
二、分析框图
总结框图:
1.通过框图分析可知:RCC章节/GPIOF章节/EXTI章节/GIC章节
2.需要分析GPIOF章节:设置引脚为输入模式
3.需要分析EXTI章节:检测中断的触发方式
3.需要分析GIC章节:设置GPIOF引脚对应的中断号
三、分析RCC章节
3.1 寄存器总线
3.2 分析RCC_MP_AHB4ENSETR寄存器
1.如何确定RCC基地址?
通过2.5.2章节
2.RCC_MP_AHB4ENSETR地址是多少呢?
RCC_MP_AHB4ENSETR地址=基地址+偏移地址 = 0x50000000 + 0xA28 = 0x50000A28
3.如何设置GPIOF控制器使能?
0x50000A28地址的第5位置1,设置GPIOF控制器使能
RCC_MP_AHB4ENSETR[5] = 1 -------->设置GPIOF控制器使能工作
四、分析GPIO章节
4.1 分析GPIOx_MODER寄存器
KEY1------>PF9引脚
KEY2------>PF7引脚
KEY3------>PF8引脚
1.如何确定GPIOF_MODER寄存器的地址?
地址=基地址+偏移地址=0x50007000+0x00=0x50007000
2.通过GPIOF_MODER设置PF9/PF7/PF8引脚设置为输入模式?
GPIOF_MODER[19:18]=00------>KEY1输入模式
GPIOF_MODER[15:14]=00------>KEY2输入模式
GPIOF_MODER[17:16]=00------>KEY3输入模式
五、分析EXTI章节
5.1 EXTI章节分析
5.1 分析EXTI_EXTICR3寄存器
EXTI_EXTICR3:EXTI external interrupt selection registe
EXTI:外部中断选择寄存器 功能:GPIO控制器和EXTI控制器进行连接
思考:1.EXTI_EXTICRn(n:1~4),为什么有4个EXTI_EXTICRn这样控制器?
1)通过EXTI框图分析可知,一共有16个EXTI(EXTI0~EXIT15)
2)EXTI_EXTICRn寄存器每8位管理一个EXTI,一个寄存器32位,最多管理4个EXTI
3)要想管理16个EXTI,需要4个这样EXTI_EXTICRn控制器
key1------>PF9------>EXTI9-------->EXTI_EXTICR3[15:8] = 0x05
key2------>PF7------>EXTI7-------->EXTI_EXTICR2[31:24] = 0x05
key3------>PF8------>EXTI8-------->EXTI_EXTICR3[7:0] = 0x05
思考2:有没有什么公式可以直接推出哪一个寄存器的哪几位
EXTI编号 / 4 = 商 ...... 余数
商+1 :对应的哪一个寄存器
余数*8:对应寄存器8位中的最低位
key1------>PF9------>EXTI9--->9 / 4 = 2.....1--->EXTI_EXTICR3[15:8] = 0x05
key2------>PF7------>EXTI7--->7 / 4 = 1.....3--->EXTI_EXTICR2[31:24] = 0x05
key3------>PF8------>EXTI8--->8 / 4 = 2.....0--->EXTI_EXTICR3[7:0] = 0x05
5.2 分析EXTI_FTSR1寄存器
1.需要知道EXTI7/EXTI8/EXTI9对应输入事件编号是多少呢?
通过芯片手册21.3章节进行查看
2.EXTI7/EXTI8/EXTI9对应设置EXTI_FTSR1位数:
key1------>PF9------>EXTI9--->对应事件9--->EXTI_FTSR1[9] = 0x1
key2------>PF7------>EXTI7--->对应事件7--->EXTI_FTSR1[7] = 0x1
key3------>PF8------>EXTI8--->对应事件8--->EXTI_FTSR1[8] = 0x1
3.地址
地址 = 基地址 + 偏移地址 = 0x5000D000 + 0x004 = 0x5000D004
5.3 分析EXTI_IMR1寄存器
1.需要知道EXTI7/EXTI8/EXTI9对应输入事件编号是多少呢?
通过芯片手册21.3章节进行查看
2.EXTI7/EXTI8/EXTI9对应设置EXTI_IMR1位数:
key1------>PF9------>EXTI9--->对应事件9--->EXTI_IMR1[9] = 0x1--->中断不屏蔽
key2------>PF7------>EXTI7--->对应事件7--->EXTI_IMR1[7] = 0x1--->中断不屏蔽
key3------>PF8------>EXTI8--->对应事件8--->EXTI_IMR1[8] = 0x1--->中断不屏蔽
3.地址
地址 = 基地址 + 偏移地址 = 0x5000D000 + 0x080 = 0x5000D080
5.4 分析EXTI_FPR1寄存器
1.rc_w1: rc--->可读 w1--->写1清除中断挂起标志位
读0:中断没有发生
读1:中断发生
写0:表示没有清除中断挂起标志位
写1:表示清除中断挂起标志位
2.EXTI7/EXTI8/EXTI9对应设置EXTI_FPR1位数:
key1------>PF9------>EXTI9--->对应事件9--->EXTI_FPR1[9] = 0x1--->清除中断挂起标志位
key2------>PF7------>EXTI7--->对应事件7--->EXTI_FPR1[7] = 0x1--->清除中断挂起标志位
key3------>PF8------>EXTI8--->对应事件8--->EXTI_FPR1[8] = 0x1--->清除中断挂起标志位
3.地址
地址 = 基地址 + 偏移地址 = 0x5000D000 + 0x010 = 0x5000D010
六、分析GICD章节
6.1 介绍
Software generated interrupts (SGI):软件中断号(ID:0~15)
Private peripheral interrupts (PPI):私有的外设中断号(ID:16~31)
Shared peripheral interrupts (SPI):共享外设中断号(ID:32~287)
6.2 分析GICD_CTLR寄存器
设置GICD层CPU0组使能
GICD_CTLR[0] = 1
6.3 分析GICD_ISENABLERx寄存器
1.思考:GICD_ISENABLERx:中断设置使能寄存器,这个寄存器为什么有9个?
1)GIC层一共管理288个中断号(16个SGI,16个PPI,256个SPI)
2)GICD_ISENABLERx每一位管理一个中断号,所以一个寄存器最多管理32个中断号
3)要想管理288个中断号,需要 288 / 32 = 9个这样的寄存器
2.思考:key1/key2/key3按键对应的中断号是多少?(通过21.2章节查找)
key1------>PF9------>EXTI9--->对应事件9--->中断号99
key2------>PF7------>EXTI7--->对应事件7--->中断号97
key3------>PF8------>EXTI8--->对应事件8--->中断号98
3.key1/key2/key3对应的中断号需要设置哪一个GICD_ISENABLERx寄存器的哪几位
key1------>PF9------>EXTI9--->对应事件9--->中断号99--->GICD_ISENABLER3[3] = 1
key2------>PF7------>EXTI7--->对应事件7--->中断号97--->GICD_ISENABLER3[1] = 1
key3------>PF8------>EXTI8--->对应事件8--->中断号98--->GICD_ISENABLER3[2] = 1
4.有没有什么公式,直接可以计算出哪一个GICD_ISENABLERx寄存器的哪几位
公式: 中断号 / 32 = 商 ...... 余数
商:中断号对应要操作的寄存器
余数:中断号对应操作寄存器的位数
key1------>PF9------>EXTI9--->对应事件9--->中断号99---> 99 / 32 = 3 .... 3--->GICD_ISENABLER3[3] = 1
key2------>PF7------>EXTI7--->对应事件7--->中断号97---> 97 / 32 = 3 .... 1--->GICD_ISENABLER3[1] = 1
key3------>PF8------>EXTI8--->对应事件8--->中断号98---> 98 / 32 = 3 .... 2--->GICD_ISENABLER3[2] = 1
6.4 分析GICD_IPRIORITYRx寄存器
1.思考:GICD_IPRIORITYRx:中断优先级设置寄存器,这个寄存器为什么有72个?
1)GIC层一共管理288个中断号(16个SGI,16个PPI,256个SPI)
2)GICD_ISENABLERx每八位管理一个中断号,所以一个寄存器最多管理4个中断号
3)要想管理288个中断号,需要 288 / 4 = 72个这样的寄存器
2.思考:key1/key2/key3按键对应的中断号是多少?(通过21.2章节查找)
key1------>PF9------>EXTI9--->对应事件9--->中断号99
key2------>PF7------>EXTI7--->对应事件7--->中断号97
key3------>PF8------>EXTI8--->对应事件8--->中断号98
3.有没有什么公式,直接可以计算出哪一个GICD_ISENABLERx寄存器的哪几位
公式: 中断号 / 4 = 商 ...... 余数
商:中断号对应要操作的寄存器
余数*8+3:中断号对应操作寄存器的位数
key1------>PF9------>EXTI9--->对应事件9--->中断号99---> 99 / 4 = 24 .... 3--->GICD_IPRIORITYR24[31:27]
key2------>PF7------>EXTI7--->对应事件7--->中断号97---> 97 / 4 = 24 .... 1--->GICD_IPRIORITYR24[15:11]
key3------>PF8------>EXTI8--->对应事件8--->中断号98---> 98 / 4 = 24 .... 2--->GICD_IPRIORITYR24[23:19]
4.注意点:中断优先级设置时,数字越小代表优先级越高
6.5 分析GICD_ITARGETSRx寄存器
1.思考:GICD_ITARGETSRx:中断优先级设置寄存器,这个寄存器为什么有72个?
1)GIC层一共管理288个中断号(16个SGI,16个PPI,256个SPI)
2)GICD_ITARGETSRx每八位管理一个中断号,所以一个寄存器最多管理4个中断号
3)要想管理288个中断号,需要 288 / 4 = 72个这样的寄存器
2.思考:key1/key2/key3按键对应的中断号是多少?(通过21.2章节查找)
key1------>PF9------>EXTI9--->对应事件9--->中断号99
key2------>PF7------>EXTI7--->对应事件7--->中断号97
key3------>PF8------>EXTI8--->对应事件8--->中断号98
3.有没有什么公式,直接可以计算出哪一个GICD_ITARGETSRx寄存器的哪几位
公式: 中断号 / 4 = 商 ...... 余数
商:中断号对应要操作的寄存器
余数*8:中断号对应操作寄存器的位数
key1------>PF9------>EXTI9--->对应事件9--->中断号99---> 99 / 4 = 24 .... 3--->GGICD_ITARGETSR24[25:24] = 0bx1
key2------>PF7------>EXTI7--->对应事件7--->中断号97---> 97 / 4 = 24 .... 1--->GICD_ITARGETSR24[9:8] = 0bx1
key3------>PF8------>EXTI8--->对应事件8--->中断号98---> 98 / 4 = 24 .... 2--->GICD_ITARGETSR24[17:16] = 0bx1
4.如何确定GICD_ITARGETSRx中这两位设置的值?
0bx1----->分配给CPU0
0b1x----->分配给CPU1
0b11----->分配给CPU0和CPU1
6.6 分析GICD_ICPENDRx寄存器
1.思考:GICD_ICPENDRx:中断清除GICD层挂起标志位寄存器,这个寄存器为什么有9个?
1)GIC层一共管理288个中断号(16个SGI,16个PPI,256个SPI)
2)GICD_ICPENDRx每一位管理一个中断号,所以一个寄存器最多管理32个中断号
3)要想管理288个中断号,需要 288 / 32 = 9个这样的寄存器
2.思考:key1/key2/key3按键对应的中断号是多少?(通过21.2章节查找)
key1------>PF9------>EXTI9--->对应事件9--->中断号99
key2------>PF7------>EXTI7--->对应事件7--->中断号97
key3------>PF8------>EXTI8--->对应事件8--->中断号98
3.key1/key2/key3对应的中断号需要设置哪一个GICD_ICPENDRx寄存器的哪几位
key1------>PF9------>EXTI9--->对应事件9--->中断号99--->GICD_ICPENDR3[3] = 1
key2------>PF7------>EXTI7--->对应事件7--->中断号97--->GICD_ICPENDR3[1] = 1
key3------>PF8------>EXTI8--->对应事件8--->中断号98--->GICD_ICPENDR3[2] = 1
4.有没有什么公式,直接可以计算出哪一个GICD_ISENABLERx寄存器的哪几位
公式: 中断号 / 32 = 商 ...... 余数
商:中断号对应要操作的寄存器
余数:中断号对应操作寄存器的位数
key1------>PF9------>EXTI9--->对应事件9--->中断号99---> 99 / 32 = 3 .... 3--->GICD_ICPENDR3[3] = 1
key2------>PF7------>EXTI7--->对应事件7--->中断号97---> 97 / 32 = 3 .... 1--->GICD_ICPENDR3[1] = 1
key3------>PF8------>EXTI8--->对应事件8--->中断号98---> 98 / 32 = 3 .... 2--->GICD_ICPENDR3[2] = 1
七、分析GICC章节
7.1 分析GICC_CTLR寄存器
CTRL[0] = 1 cpu组0使能
7.2 分析GICC_PMR寄存器
GICC_PMR:中断优先级寄存器
这个寄存器设置的值,需要比GICD层设计的中断优先级的值要大
7.3 分析GICC_IAR寄存器
GICC_IAR作用:获取中断号
GICC_IAR[9:0]:获取按键的中断号
7.4 分析GICC_EOIR寄存器
GICC_EOIR作用:清除中断号
GICC_EOIR[9:0]:清除按键的中断号
cortex - A7 核代码
#ifndef __KEY_H__
#define __KEY_H__
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_exti.h"
#include "stm32mp1xx_gic.h"
/*****KEY1---->PF9**********/
//初始化EXTI层
void pf9_exti_init();
//初始化GICD层
void pf9_gicd_init();
//初始化GICC层
void pf9_gicc_init();
#endif
#include "key.h"
/*****KEY1---->PF9**********/
//初始化EXTI层
void pf9_exti_init()
{
/*****RCC章节初始化******/
//1.设置GPIOF组时钟使能 MP_AHB4ENSETR[5] = 1
RCC->MP_AHB4ENSETR |= 0x1<<5;
/*****GPIO章节初始化******/
//1.设置PF9引脚为输入模式 MODER[19:18] = 00
GPIOF->MODER &=(~(0x3<<18));
/*****EXTI章节初始化******/
//1.设置PF9引脚和EXIT9控制器进行连接 EXTICR3[15:8] = 0x05
EXTI->EXTICR3 &=(~(0xff<<8));
EXTI->EXTICR3 |= (0x05<<8);
//2.设置PF9引脚检测方式下降沿 FTSR1[9] = 1
EXTI->FTSR1 |= 0x1<<9;
//3.设置PF9引脚中断不屏蔽 C1IMR1[9] = 1
EXTI->C1IMR1 |= 0x1<<9;
}
//初始化GICD层
void pf9_gicd_init()
{
//1.设置GICD层全局中断使能寄存器 CTRL[0] = 1
GICD->CTRL |=0x1<<0;
//2.设置GICD层中断使能寄存器 ISENABLER[3] 第三位 1
GICD->ISENABLER[3] |= 0x1<<3;
//3.设置GICD层中断优先级寄存器IPRIORITYR[24] [31:27]
GICD->IPRIORITYR[24] &=(~(0x1f<<27));
//4.设置GICD层中断目标分配寄存器 ITARGETSR[24] [25:24] = 01
GICD->ITARGETSR[24] &=(~(0x3<<24));
GICD->ITARGETSR[24] |=0x1<<24;
}
//初始化GICC层
void pf9_gicc_init()
{
//1.设置GICC层全局中断使能寄存器 CTRL[0] = 1
GICC->CTRL |=0x1<<0;
//2.设置GICC层中断优先级寄存器 PMR[7:3]
GICC->PMR &=(~(0x1f<<3));
GICC->PMR |=0x1f<<3;
}
cortex - M4核
一、中断实验接口
key1------>PF9------>检测方式:下降沿
key2------>PF7------>检测方式:下降沿
key3------>PF8------>检测方式:下降沿
光电开关------>PE15------>检测方式:上升沿(通过调节滑动变阻器R55,让LD5灯点亮)
火焰传感器------>PF5------>检测方式:上升沿(通过调节滑动变阻器R67,让LD6灯点亮)
人体红外------>PF12------>检测方式:上升沿
二、电路图分析
2.1 光电开光分析
2.2 火焰传感器
火焰传感器(即红外接收二极管)是机器人专门用来搜寻火焰的传感器,火焰传感器对火焰特别灵敏
它的原理是利用火焰产生的红外线对它非常敏感的特点
当火焰亮度变大时,发出的红外线越多,火焰传感器管教间的阻抗变小
当火焰亮度变小时,发出的红外线越少,火焰传感器管教间的阻抗变大
2.3 人体红外
三、实验目的
需要检测中断之后,让灯状态取反
四、工程配置
1.配置LED1/LED2/LED3为输出模式:PE10/PF10/PE8------>配置工程师注意:配置为输出模式,给到M4核
2.配置PF9/PF7/PF8/PE15/PF5/PF12为GPIO_EXTI模式:配置工程师注意:配置为GPIO_EXTI模式,给到M4核
五、导出工程
六、代码编写
void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
{
switch(GPIO_Pin)
{
//KEY2 --- PF10
case GPIO_PIN_7:
HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);
break;
//KEY3 --- PE10
case GPIO_PIN_8:
HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_10);
break;
//KEY1 --- PE8
case GPIO_PIN_9:
HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_8);
break;
}
}