按键控制LED灯

RCC和GPIO初始化函数:

EXTI初始化函数:通用的函数,对KEY1/KEY2/KEY3进行使用

void hal_exti_init(事件编号,GPIOF组对应编号,触发方式)

GIC层初始化函数:通用的函数,对KEY1/KEY2/KEY3进行使用

void hal__GIC_init(中断id,优先级)


实验现象:

当按键1按下之后,1)打印一句话,并且需要打印出中断号 2)LED1灯的状态进行取反

当按键2按下之后,1)打印一句话,并且需要打印出中断号2)LED2灯的状态进行取反

当按键3按下之后,1)打印一句话,并且需要打印出中断号 2)LED3灯的状态进行取反
 

key_light.h

#ifndef __KEY_LIGHT_H__
#define __KEY_LIGHT_H__

#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_exti.h"
#include "stm32mp1xx_gic.h"

//RCC,GPIO初始化
//pf_num:PF组引脚的编号
void rcc_gpio_init(unsigned int pf_num);

//EXTI初始化
//event_num:事件编号
//gpiof_num:GPIOF组对应编号
//type:触发方式 1为下降沿触发
void exti_init(unsigned int event_num,unsigned int gpiof_num,unsigned int type);

//GIC初始化
//id:中断号     
//pri:优先级    0-2^5-1
void gic_init(unsigned int id,unsigned int pri);

//灯的初始化
void led_init();

#endif

key_light.c

#include"key_light.h"

//按键初始化
//初始化RCC,GPIO章节//RCC,GPIO初始化
//pf_num:PF组引脚的编号
void rcc_gpio_init(unsigned int pf_num)
{
    /******RCC章节初始化******/
    //1、GPIOF组控制器使能      MP_AHB4ENSETR[5]=1
    RCC->MP_AHB4ENSETR |= (0x1 << 5);

    /******GPIO章节初始化******/
    //1、将PF(pf_num)引脚设置为输入模式    PF9--->MODER[19:18]=00   PF7--->MODER[15:14]=00  PF8--->MODER[17:16]=00
    GPIOF->MODER &= (~(0x3 << (2*pf_num)));
}

//EXTI初始化
//event_num:事件编号
//gpiof_num:GPIOF组对应编号
//type:触发方式 1为下降沿触发,0为上升沿触发
void exti_init(unsigned int event_num,unsigned int gpiof_num,unsigned int type)
{
    //event_num%4求商
    unsigned int s = event_num / 4;
    //event_num%4取余
    unsigned int yu = event_num % 4;
    //EXTICR1的地址
    unsigned int *p = &(EXTI->EXTICR1);
    //1、设置中断选择寄存器
    *(p+s) &= (~(0xff << (8*yu)));
    *(p+s) |= (gpiof_num << (8*yu));

    //2、设置事件触发方式
    if(type == 1)
        //设置事件触发为下降沿
        EXTI->FTSR1 |= (0x1 << event_num);
    else if(type == 0)
        //设置事件触发为下降沿
        EXTI->RTSR1 |= (0x1 << event_num);

    //3、设置中断不屏蔽
    EXTI->C1IMR1 |= (0x1 << event_num);
}


//GIC初始化
//id:中断号     
//pri:优先级    0-2^5-2
void gic_init(unsigned int id,unsigned int pri)
{
    /******GICD章节初始化******/
    //1、设置中断使能寄存器
    GICD->ISENABLER[id / 32] |= (0x1 << (id % 32));

    //2、设置全局控制
    GICD->CTRL |= 0x1;
    
    //3、设置优先级
    GICD->IPRIORITYR[id / 4] &= (~(0x1f << ((id % 4)*8+3)));
    GICD->IPRIORITYR[id / 4] |= (pri << ((id % 4)*8+3));

    //4、设置目标分配寄存器
    GICD->ITARGETSR[id / 4] &= (~(0x3 << ((id % 4)*8)));
    GICD->ITARGETSR[id / 4] |= (0x1 << ((id % 4)*8));


    /******GICC章节初始化******/
    //1、设置优先级     PMR[7:3]
    GICC->PMR &= (~(0x1f << 3));
    GICC->PMR |= (0x1f << 3);
    //2、设置中断全局控制器       CTLR[0]=1
    GICC->CTRL |= 0x1;
}

//灯的初始化
void led_init()
{
    /*****RCC章节*******/
    //1、GPIOE,GPIOF使能
    RCC->MP_AHB4ENSETR |= (0x1 << 4);
    RCC->MP_AHB4ENSETR |= (0x1 << 5);

    /*****GPIO章节*******/
    //LED1
    //1、设置模式为输出模式     MODER[21:20] = 01
    GPIOE->MODER &= (~(0x3 << 20));
    GPIOE->MODER |= (0x1 << 20);
    //2、设置输出类型,推挽模式     OTYPER[10] = 0
    GPIOE->OTYPER &= (~(0x1 << 10));
    //3、设置输出速度,低速         OSPEEDR[21:20] = 00
    GPIOE->OSPEEDR &= (~(0x3 << 20));
    //4、不设置上拉下拉电阻         PUPDR[21:20] = 00
    GPIOE->PUPDR &= (~(0x3 << 20));
    
    //LED2
    //1、设置模式为输出模式     MODER[21:20] = 01
    GPIOF->MODER &= (~(0x3 << 20));
    GPIOF->MODER |= (0x1 << 20);
    //2、设置输出类型,推挽模式     OTYPER[10] = 0
    GPIOF->OTYPER &= (~(0x1 << 10));
    //3、设置输出速度,低速         OSPEEDR[21:20] = 00
    GPIOF->OSPEEDR &= (~(0x3 << 20));
    //4、不设置上拉下拉电阻         PUPDR[21:20] = 00
    GPIOF->PUPDR &= (~(0x3 << 20));

    //LED3
    //1、设置模式为输出模式     MODER[17:16] = 01
    GPIOE->MODER &= (~(0x3 << 16));
    GPIOE->MODER |= (0x1 << 16);
    //2、设置输出类型,推挽模式     OTYPER[8] = 0
    GPIOE->OTYPER &= (~(0x1 << 8));
    //3、设置输出速度,低速         OSPEEDR[17:16] = 00
    GPIOE->OSPEEDR &= (~(0x3 << 8));
    //4、不设置上拉下拉电阻         PUPDR[17:16] = 00
    GPIOE->PUPDR &= (~(0x3 << 8));
    
}

main.c

#include"key_light.h"

#define KEY1_PF_NUM 9
#define KEY2_PF_NUM 7
#define KEY3_PF_NUM 8
#define KEY1_EVENT_NUM 9
#define KEY2_EVENT_NUM 7
#define KEY3_EVENT_NUM 8
#define GPIOF_NUM 5
#define TYPE_FALLING 1
#define TYPE_RISING 0
#define KEY1_ID 99
#define KEY2_ID 97
#define KEY3_ID 98
#define KEY1_PRI 1
#define KEY2_PRI 2
#define KEY3_PRI 3

int main()
{
	//初始化key1
	//key1----->PF9----->EXTI9----->99
	rcc_gpio_init(KEY1_PF_NUM);
	exti_init(KEY1_EVENT_NUM,GPIOF_NUM,TYPE_FALLING);
	gic_init(KEY1_ID,KEY1_PRI);

	//初始化key2
	//key2----->PF7----->EXTI7----->97
	rcc_gpio_init(KEY2_PF_NUM);
	exti_init(KEY2_EVENT_NUM,GPIOF_NUM,TYPE_FALLING);
	gic_init(KEY2_ID,KEY2_PRI);
	
	//初始化key3
	//key3----->PF8----->EXTI8----->98
	rcc_gpio_init(KEY3_PF_NUM);
	exti_init(KEY3_EVENT_NUM,GPIOF_NUM,TYPE_FALLING);
	gic_init(KEY3_ID,KEY3_PRI);

	//初始化LED1,LED2,LED3
	led_init();
	while(1)
	{
	}
	return 0;
}

do_irq.c

#include"key_light.h"
extern void printf(const char *fmt, ...);
void do_irq(void) 
{
	
	//获取中断号
	unsigned int num;
	num = (GICC->IAR & (0x3ff));

	//判断中断号
	switch (num)
	{
	case 99:
		printf("this is key1#####\n");
		printf("num = %d\n",num);

		//LED1状态取反
		GPIOE->ODR ^= (0x1 << 10);

		//设置key1清除EXTI层挂起中断标志位     FPR1[9]=1
    	EXTI->FPR1 |= (0x1 << 9);
		//设置key1清除GICD层中断挂起标志位		ICPENDR3[3]=1
    	GICD->ICPENDR[3] |= (0x1 << 3);
		break;
	case 97:
		printf("this is key2#####\n");
		printf("num = %d\n",num);

		//LED2状态取反
		GPIOF->ODR ^= (0x1 << 10);

		//设置key2清除EXTI层挂起中断标志位     FPR1[7]=1
    	EXTI->FPR1 |= (0x1 << 7);
		//设置key2清除GICD层中断挂起标志位		ICPENDR3[1]=1
    	GICD->ICPENDR[3] |= (0x1 << 1);
		break;
	case 98:
		printf("this is key3#####\n");
		printf("num = %d\n",num);

		//LED3状态取反
		GPIOE->ODR ^= (0x1 << 8);
		//设置key3清除EXTI层挂起中断标志位     FPR1[8]=1
    	EXTI->FPR1 |= (0x1 << 8);
		//设置key3清除GICD层中断挂起标志位		ICPENDR3[2]=1
    	GICD->ICPENDR[3] |= (0x1 << 2);
		break;
	default:
		break;
	}
	//清除中断号
	GICC->EOIR = num;    
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值