按键中断封装

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灯的状态进行取反

main.c

#include "key.h"

#include "led.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++);

}



#define EXTI7_INPUT_EVENT 7

#define EXTI8_INPUT_EVENT 8

#define EXTI9_INPUT_EVENT 9

#define GPIOGROUP 0x05

#define KEY1_ID 99

#define KEY2_ID 97

#define KEY3_ID 98

#define IPR_EXTI7 7

#define IPR_EXTI8 8

#define IPR_EXTI9 9


int main()

{

     all_led_init();

	key_gpio_rcc_init();



	//KEY1

	hal_exti_key_init(EXTI9_INPUT_EVENT,GPIOGROUP,Falling);

	hal_gic_key_init(KEY1_ID,IPR_EXTI9);

	//KEY2

	hal_exti_key_init(EXTI7_INPUT_EVENT,GPIOGROUP,Falling);

	hal_gic_key_init(KEY2_ID,IPR_EXTI7);

	//KEY3

	hal_exti_key_init(EXTI8_INPUT_EVENT,GPIOGROUP,Falling);

	hal_gic_key_init(KEY3_ID,IPR_EXTI8);

	while(1)

	{

		}

	return 0;

}

led.h:

#ifndef __LED_H__
#define __LED_H__
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_rcc.h"
//定义寄存器组织结构体

//定义GPIOE和GPIOF


 void all_led_init();
 

#endif
 

 key.h:

#ifndef __KEY_H__
#define __KEY_H__

#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_exti.h"
#include "stm32mp1xx_gic.h"
typedef enum//枚举
{
    Rising =0, //上升沿
    Falling, //下降沿
}triger_t;
//GPIO章节和RCC章节初始化
void key_gpio_rcc_init();
//EXTI章节初始化
void hal_exti_key_init(unsigned int input_event,
		unsigned int gpiogroup,triger_t trigger);
//GIC章节初始化
void hal_gic_key_init(unsigned int id,unsigned int ipr);

#endif

key.c

#include "key.h"
void key_gpio_rcc_init()
{ 
    //KEY1->PF9
    //KEY2->PF7
    //KEY3->PF8
    //设置GPIOF使能 MP_AHB4ENSETR[5]=1
    RCC->MP_AHB4ENSETR |=(0x1<<5);
    //设置PF9为输入模式 MODER[19:18]=00
     GPIOF->MODER&=(~(0x3<<18));
   //设置PF7为输入模式 MODER[15:14]=00
     GPIOF->MODER&=(~(0x3<<14));
 //设置PF8为输入模式 MODER[17:16]=00
     GPIOF->MODER&=(~(0x3<<16));

}

//EXIT章节初始化
//input_event:事件编号
//gpiogroup:gpio对应组的编号
//trigger:触发方式
void hal_exti_key_init(unsigned int input_event,
		unsigned int gpiogroup,triger_t trigger)
        {
       //设置GPI引脚和EXTI进行连接
       switch (input_event/4)
       {
       case 1:
          EXTI->EXTICR2 &=(~(0xff<<(input_event%4*8)));
          EXTI->EXTICR2 |=(gpiogroup<<(input_event%4*8));
           break;
        case 2:
         EXTI->EXTICR3 &=(~(0xff<<(input_event%4*8)));
         EXTI->EXTICR3 |=(gpiogroup<<(input_event%4*8));
        break;
        case 3:
        break;
         }
         //设置中断触发方式
         if(trigger==Falling)//触发方式为下降沿触发
         {
             EXTI->FTSR1|=(0x1<<input_event);
         }
           else//触发方式为上升沿触发
           {
               EXTI->RTSR1 |=(0x1<<input_event);
           }
            //设置中断不屏蔽
            EXTI->C1IMR1 |=(0x1<<input_event);
 }

//GIC章节初始化
//中断id
//优先级
void hal_gic_key_init(unsigned int id,unsigned int ipr)
{
   //设置GICD层中断使能寄存器
   GICD->ISENABLER[id/32]&=(~(0x1<<(id%32)));
   GICD->ISENABLER[id/32] |=(0x1<<(id%32));
   //设置GICD层中断优先级寄存器
   GICD->IPRIORITYR[id/4] &=(~(0x1f<<(id%4 *8 +3)));
  GICD->IPRIORITYR[id/4] |=(ipr<<(id%4 *8 +3));
  //设置GICD层中断目标分配寄存器
  GICD->ITARGETSR[id/4] &=(~(0x3<<(id%4*8)));
  GICD->ITARGETSR[id/4] |=(0x1<<(id%4*8));
//设置GICD层中断全局控制器
GICD->CTRL |=(0x1<<0);
//设置GICC层中断优先级寄存器
GICC->PMR |=(0x1f<<3);
//设置GICC层中断全局控制器
GICC->CTRL |= (0x1<<0);


}

do_irq.c:

#include "key.h"
#include "led.h"
extern void delay_ms(int ms);
extern void printf(const char *fmt, ...);
//按键按下之后,打印一句话
void do_irq(void) 
{
    unsigned int num;
  //获取中断号
  num=GICC->IAR &0x3ff;
  //判断中断号
  switch (num)
  {
  case 97:// KEY2 ---->LED2---->PF10
  GPIOF->ODR ^= (0x1 << 10);
  printf("key2 interrupt id = %d\n",num);
     EXTI->FPR1 |= (0x1 << 7);
	GICD->ICPENDR[3] |= (0x1 << 1);
      break;
  case 98:// KEY3 ---->LED3--->PE8
  GPIOE->ODR ^= (0x1 << 8);
        printf("key3interrupt id = %d\n",num);
   EXTI->FPR1 |= (0x1 << 8);
	GICD->ICPENDR[3] |= (0x1 << 2);
  break;
  case 99://KEY1 ---->LED1---->PE10
  GPIOE->ODR ^= (0x1 << 10);
  printf("key1 interrupt id = %d\n",num);
   delay_ms(500);
   EXTI->FPR1 |= (0x1 << 9);
	GICD->ICPENDR[3] |= (0x1 << 3);
  break;
 
  }
  //5.清除中断号EOIR
	GICC->EOIR = num;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,针对您的需求,我们可以封装一个按键函数,来实现多个按键的消抖。具体实现如下: ```c #include "F2837xD_Gpio.h" #include "F2837xD_Intrupt.h" #include "F2837xD_Examples.h" #define KEY_DEBOUNCE_TIME 100 //按键消抖时间,单位为毫秒 void InitKeyGpio(void); interrupt void KeyISR(void); volatile Uint16 keyStatus = 0; //按键状态标志,用于记录按键是否按下 void InitKeyGpio(void) { EALLOW; GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0; //GPIO0设置为普通I/O口 GpioCtrlRegs.GPADIR.bit.GPIO0 = 0; //GPIO0设置为输入 GpioCtrlRegs.GPAQSEL1.bit.GPIO0 = 2; //GPIO0设置为双边沿中断 GpioCtrlRegs.GPACTRL.bit.QUALPRD0 = 0xFF; //采样周期为255个SYSCLKOUT周期 IER |= M_INT1; //使能INT1中断 PieCtrlRegs.PIEIER1.bit.INTx7 = 1; //使能GPIO0中断 EINT; //开全局中断 EDIS; } interrupt void KeyISR(void) { static Uint16 keyCount = 0; //按键计数器,用于计算按键消抖时间 if(GpioDataRegs.GPADAT.bit.GPIO0 == 0) //如果按键按下 { keyCount++; //计数器加1 if(keyCount >= KEY_DEBOUNCE_TIME) //如果计数器大于等于按键消抖时间 { keyStatus = 1; //按键状态标志置1 keyCount = 0; //计数器清零 } } else //如果按键弹起 { keyCount = 0; //计数器清零 } PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; //清除中断标志 } Uint16 GetKeyStatus(void) { Uint16 status = keyStatus; //获取按键状态 keyStatus = 0; //按键状态标志清零 return status; //返回按键状态 } ``` 在主函数中,调用`InitKeyGpio()`函数初始化按键GPIO口,并在需要的地方调用`GetKeyStatus()`函数获取按键状态即可。 ```c void main(void) { InitSysCtrl(); InitKeyGpio(); while(1) { if(GetKeyStatus()) //如果按键被按下 { //执行相应的操作 } } } ``` 这样,就实现了一个简单的按键函数,可以支持多个按键的消抖。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值