基于GD32单片机的独立按键检测

文章介绍了基于GD32L233单片机的按键检测函数,包括按键状态定义、GPIO初始化、弱声明的函数处理(抬起、按下、长按),以及按键检测的核心逻辑。代码示例展示了如何检测多个按键的状态变化,并触发相应的事件处理函数。
摘要由CSDN通过智能技术生成

这是一段独立按键的检测函数 ,仅供参考,错的地方多多包含

首先定义一下,按键的按下的时间和要检测的个数

#define PRESS_LONG_TIME  1000
#define PRESS_CHECK_TIME  70
#define KEY_BUFF_LEN  32 

 我这里定义了五个按键,根据上面可知最多可检测32位按键

#define KEY0 (!gpio_input_bit_get(GPIOB,GPIO_PIN_13))
#define KEY1 (!gpio_input_bit_get(GPIOB,GPIO_PIN_14))
#define KEY2 (!gpio_input_bit_get(GPIOB,GPIO_PIN_15))
#define KEY3 (!gpio_input_bit_get(GPIOC,GPIO_PIN_6))
#define KEY4 (!gpio_input_bit_get(GPIOC,GPIO_PIN_7))

 使用个枚举定义一下按键的状态.typedef+enum,大家可以先了解一下通过使用 typedef,来定义一个新类型名称的用法,typedef可以声明新的类型名来代替已有的类型名,但却不能增加新的类型。我们可以将 enum 定义的枚举类型命名为KEY_STATUS_DEF ,以后就可以使用 Weekday 来声明变量,而不需要关注实际的枚举值。

typedef enum 
{
    KEY_UP,    //按键抬起
    KEY_DOWN,       //按键按下
    KEY_PRESS,        //按键短按
    KEY_PRESS_LONG,     //按键长按
}KEY_STATUS_DEF;//新类型名称

typedef+struct,与上面枚举同理。嵌套了枚举的定义的新名称status。 

typedef struct
{
    uint64_t time;
    KEY_STATUS_DEF status;
}Key_flag;//新的结构体

//按键状态
Key_flag    key_flag[KEY_BUFF_LEN]={0};//将key_flag[KEY_BUFF_LEN]={0}替换掉Key_flag,里面包含着按键个数
//当前实时按键状态
uint32_t key_status =0;

然后铺垫完成,开始进入到最简单的gpio初始化,因为我用的是GD32l233系列的国产单片机,可能固件库会与stm32不同,大家用的时候注意一下。

void key_gpio_Init(void)
{
  rcu_periph_clock_enable(RCU_GPIOC);
    rcu_periph_clock_enable(RCU_GPIOB);
    gpio_mode_set(GPIOC,GPIO_MODE_INPUT,GPIO_PUPD_PULLUP ,GPIO_PIN_6 | GPIO_PIN_7);
    gpio_mode_set(GPIOB,GPIO_MODE_INPUT,GPIO_PUPD_PULLUP ,GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);                                                                                                     
}

在这里使用弱声明,可更好的调用函数 ,分别是抬起,按下,长按。

__WEAK void  KeyUp(uint8_t index)
{      
}

__WEAK void  KeyPress(uint8_t index)
{
}
__WEAK void  KeyLongPress(uint8_t index)
{
}

下面才是这段代码的重中之重,按键的检测,大家仔细理解

void Key_Check(uint16_t pointTime)
{
    uint8_t i;
    uint8_t status;
    for(i=0;i<KEY_BUFF_LEN;i++)
    {
        status=(key_status >>i) & 0x01;
        switch (key_flag[i].status)
        {
        case KEY_UP:
                if(!status)
            {
                key_flag[i].time +=pointTime;
            }
            else
            {
                key_flag[i].time =0;
                key_flag[i].status=KEY_DOWN;
            
            }
            break;
        case KEY_DOWN:
            if(!status)
                {
                    key_flag[i].time =0;
                    key_flag[i].status =KEY_UP;
                }
                else
                {
                    key_flag[i].time +=pointTime;
                    if(key_flag[i].time >=PRESS_CHECK_TIME)
                    {
                        key_flag[i].time=0;
                        key_flag[i].status =KEY_PRESS;
                        KeyPress(i);
                    }
                }
            break;
        case KEY_PRESS:
                if(!status)
                {
                    key_flag[i].time =0;
                    key_flag[i].status =KEY_UP;
                    KeyUp(i);
                }
                else
                {
                    key_flag[i].time += pointTime;
                
                    if(key_flag[i].time  >= PRESS_LONG_TIME)

                    {
                        key_flag[i].time =0;
                        key_flag[i].status=KEY_PRESS_LONG;
                        KeyLongPress(i);
                    }
                }
                
            break;
        case KEY_PRESS_LONG:
                    if(!status)
                    {
                        key_flag[i].time= 0;
                        key_flag[i].status =KEY_UP;
                        KeyUp(i);
                    }
                    else
                    {
                        key_flag[i].time +=pointTime;
                    }
                    break;
        }
    }
}

因为写法的顺序问题,再最后就是按键的初始化和线程的创建

void KeyThread (void *argument)
{
        uint8_t q;
        while(1)
        {
            osDelay(10);
            key_status =KEY0 |(KEY1<<1)|(KEY2 <<2)|(KEY3 <<3)|(KEY4 <<4);
             Key_Check(10);
            osThreadYield();
        }
        
}
 int Init_KeyThread(void)
 {
     osThreadAttr_t th ={.stack_size =256};
     osThreadId_t tidThread =osThreadNew(KeyThread,NULL,&th);
     if(tidThread ==NULL)
     {
         return(-1);
     }
     return(0);
 }
 
void Key_Init (void )
{
     Key_gpio_Init();
    Init_KeyThread();
}

可能这段代码对于大部分人来说没有什么难度,但是作为公司小白的我移植改造的第一个代码,可谓是困难重重,刚开始也有很多写法和函数上的不明白,好在有公司前辈的帮助和解惑,很感谢大佬们。

写这篇文章的意义是可以在自己复习的时候有个记录,也是可以让大家进行参考,为了写代码我也是每天逛各种资源网站,很理解书到用时方恨少的感觉。如果有什么不对的地方也很 感谢大家提出来。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值