1.中断实验:按键控制led灯
流程:
key.h
/*************************************************************************
> File Name: include/key.h
> Created Time: 2023年08月21日 星期一 17时03分20秒
************************************************************************/
#ifndef __KEY_H__
#define __KEY_H__
//引脚编号封装
#define EXTI7 7
#define EXTI8 8
#define EXTI9 9
#define GPIO_PIN_0 0
#define GPIO_PIN_1 1
#define GPIO_PIN_2 2
#define GPIO_PIN_3 3
#define GPIO_PIN_4 4
#define GPIO_PIN_5 5
#define GPIO_PIN_6 6
#define GPIO_PIN_7 7
#define GPIO_PIN_8 8
#define GPIO_PIN_9 9
#define GPIO_PIN_10 10
#define GPIO_PIN_11 11
#define GPIO_PIN_12 12
#define GPIO_PIN_13 13
#define GPIO_PIN_14 14
#define GPIO_PIN_15 15
#include "stm32mp1xx_exti.h"
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_gic.h"
typedef enum{
FALL_DIS, //禁用下降沿 0
FALL_EN //启用下降沿 1
}exti_ftsr1_t;
//RCC/GPIO/EXTI章节初始化
void HAL_EXTI_INIT(unsigned int pin, unsigned int gp, exti_ftsr1_t falling);
//GIC章节初始化
void HAL_GIC_INIT(unsigned int nod, unsigned int first);
//***************点灯***************//
//MODER模式寄存器
typedef enum{
INPUT, //输入 0
OUPUT, //输出 1
ALT, //复用 2
ANALOG //模拟 3
}gpio_moder_t;
//OTYPER输出类型寄存器
typedef enum{
PP, //推挽 0
OD //开漏 1
}gpio_otyper_t;
//OSPEEDR输出速率寄存器
typedef enum{
LOW, //低速 0
MED, //中速 1
HIGH, //高速 2
VERY_HIGH //快速 3
}gpio_ospeedr_t;
//PUPDR是否需要上下拉电阻寄存器
typedef enum{
NO_PU_PD, //禁止 0
PU, //上拉 1
PD, //下拉 2
RES //保留 3
}gpio_pupdr_t;
typedef struct{
gpio_moder_t moder; //模式寄存器
gpio_otyper_t otyper; //输出类型寄存器
gpio_ospeedr_t ospeedr; //输出速率寄存器
gpio_pupdr_t pupdr; //是否需要上下拉电阻寄存器
}gpio_init_t;
//GPIO引脚初始化函数 PE10 PF10 PE8
//void hal_gpio_init(GPIO组编号,引脚编号,初始化的值)
void hal_gpio_initl(gpio_t* gpiox, unsigned int pin, gpio_init_t *gpio_init);
//GPIO引脚写操作函数 0:熄灭 1:点亮
//void hal_gpio_write(GPIO组编号,引脚编号,操作的值)
void hal_gpio_writel(gpio_t* gpiox, unsigned int pin);
#endif
key.c
/*************************************************************************
> File Name: src/key.c
> Created Time: 2023年08月21日 星期一 17时03分20秒
************************************************************************/
#include "key.h"
//RCC/GPIO/EXTI章节初始化
void HAL_EXTI_INIT(unsigned int pin, unsigned int gp, exti_ftsr1_t falling)
{
//RCC使能GPIOF组 MP_AHB4ENSETR[5] = 1
RCC->MP_AHB4ENSETR |= (0x1 << 5);
//设置GPIOF引脚模式为输出
GPIOF->MODER &= (~(0x3 << (pin*2)));
//EXTI外部中断选择GPIOF
unsigned int n = pin/4 + 1;
switch (n)
{
case 3 :
EXTI->EXTICR3 &= (~(0xff << ((pin%4)*8)));
EXTI->EXTICR3 |= (gp << ((pin%4)*8));
break;
case 2:
EXTI->EXTICR2 &= (~(0xff << ((pin%4)*8)));
EXTI->EXTICR2 |= (gp << ((pin%4)*8));
break;
}
//EXTI事件触发为下降沿
EXTI->FTSR1 |= (falling << pin);
//EXTI设置不屏蔽 C1IMR1[9] = 1
EXTI->C1IMR1 |= (0X1 << pin);
}
//GIC章节初始化
void HAL_GIC_INIT(unsigned int nod, unsigned int first)
{
//1.GICD层
//使能GICD层 CTRL[0] = 1
GICD->CTRL |= (0x1 << 0);
//中断设置使能(99) ISENABLER[3]第3位写1
GICD->ISENABLER[nod/32] |= (0X1 << (nod%32));
//中断优先级设置 IPRIORITYR[24]第[31:27] = 0b00000
GICD->IPRIORITYR[nod/4] &= (first << ((nod%4)+3));
//选择CPU0 ITARGETSR[24]第[25:24] = 0b01
GICD->ITARGETSR[nod/4] &= (~(0X3 << ((nod%4)*8)));
GICD->ITARGETSR[nod/4] |= (0X1 << ((nod%4)*8));
//2.GICC层
//使能GICC层 CTRL[0] = 1
GICC->CTRL |= (0X1 << 0);
//输入中断优先级 PMR[7:3] = 0b11111
GICC->PMR |= (0x1f << 3);
}
//**************点灯******************//
void hal_gpio_initl(gpio_t* gpiox, unsigned int pin, gpio_init_t *gpio_init)
{
//1.设置gpio引脚模式MODER 每两位管理一个引脚
gpiox->MODER &= (~(0x3 << (pin * 2)));
gpiox->MODER |= (gpio_init->moder << (pin * 2));
//2.设置gpio引脚输出类型
gpiox->OTYPER &= (~(0x1 << pin));
gpiox->OTYPER |= (gpio_init->otyper << pin);
//3.设置gpio引脚输出速率
gpiox->OSPEEDR &= (~(0x3 << (pin * 2)));
gpiox->OSPEEDR |= (gpio_init->ospeedr << (pin * 2));
//4.设置gpio引脚禁止上下拉电阻
gpiox->PUPDR &= (~(0x3 << (pin * 2)));
gpiox->PUPDR |= (gpio_init->pupdr << (pin * 2));
}
void hal_gpio_writel(gpio_t* gpiox, unsigned int pin)
{
gpiox->ODR ^= (0x1 << pin);
}
do_lrq.c
#include "key.h"
extern void printf(const char *fmt, ...);
unsigned int i = 0;
void do_irq(void)
{
unsigned int num = 0;
//获取中断号
num = GICC->IAR & 0X3FF;
switch (num)
{
case 99:
{
printf("***key1***\n");
hal_gpio_writel(GPIOE, GPIO_PIN_8);
//清除EXTI层挂起标志位
EXTI->FPR1 |= (0x1 <<9);
//清除GICD层挂起标志位
GICD->ICPENDR[3] |= (0X1 <<3);
}
break;
case 97:
{
printf("***key2***\n");
hal_gpio_writel(GPIOF, GPIO_PIN_10);
//清除EXTI层挂起标志位
EXTI->FPR1 |= (0x1 <<7);
//清除GICD层挂起标志位
GICD->ICPENDR[3] |= (0X1 <<1);
}
break;
case 98:
{
printf("***key3***\n");
hal_gpio_writel(GPIOE, GPIO_PIN_10);
//清除EXTI层挂起标志位
EXTI->FPR1 |= (0x1 <<8);
//清除GICD层挂起标志位
GICD->ICPENDR[3] |= (0X1 <<2);
}
break;
}
//清除中断号
GICC->EOIR &= (~(0X3FF));
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++);
}
void led_init()
{
//初始化时钟 GPIOE和GPIOF组时钟使能
RCC->MP_AHB4ENSETR |= (0x3 << 4);
//结构体进行初始化
//gpio_init_t init;
//init.moder = OUPUT;
//init.otyper = PP;
//init.ospeedr = LOW;
//init.pupdr = NO_PU_PD;
gpio_init_t init = {OUPUT, PP, LOW, NO_PU_PD};
hal_gpio_initl(GPIOE, GPIO_PIN_10, &init);
hal_gpio_initl(GPIOF, GPIO_PIN_10, &init);
hal_gpio_initl(GPIOE, GPIO_PIN_8, &init);
}
int main()
{
led_init();
HAL_EXTI_INIT(EXTI9, 0x05, FALL_EN);
HAL_EXTI_INIT(EXTI7, 0x05, FALL_EN);
HAL_EXTI_INIT(EXTI8, 0x05, FALL_EN);
HAL_GIC_INIT(99, 9);
HAL_GIC_INIT(97, 7);
HAL_GIC_INIT(98, 8);
while(1)
{
}
return 0;
}