#ifndef key_diver_h
#define key_diver_h
#include"stdint.h"
typedef enum {
KEY_CODE_1,
KEY_CODE_2,
KEY_CODE_3,
KEY_CODE_NUM
}ENUM_KEY_CODE;
typedef enum {
KEY_STATE_IDLE,
KEY_STATE_CLICK,
KEY_STATE_DBCLICK,
KEY_STATE_LONGHOLD,
KEY_STATE_HOLDING,
KEY_STATE_WAIT_TRIG,
}ENUM_KEY_STARE;
#define KEY_STATE_LONGHOLD_time_us (3000000)
#define KEY_wait_time_us (300000)
extern void keycodeupdate( ENUM_KEY_CODE keycode);
typedef void (*keycodeevent_cb)(ENUM_KEY_CODE keycode,ENUM_KEY_STARE state);
extern void keycodeinit( ENUM_KEY_CODE keycode,uint32_t group,uint32_t pin);
extern void keycodeupdate( ENUM_KEY_CODE keycode);
extern void keycodeeventreg(keycodeevent_cb func);
#endif
#include"stdio.h"
#include"gd32f30x.h"
#include"keydiver.h"
#include"stdint.h"
static keycodeevent_cb pkeycodecb =0;
static keycodeeventreg (keycodeevent_cb func){pkeycodecb=func;}
typedef struct{
uint32_t enable;
uint32_t group;
uint32_t pin;
uint32_t ishold;
unsigned long long holdchek;
unsigned long long holdtick;
ENUM_KEY_STARE state;
ENUM_KEY_CODE keycode;
}tafkeyinfo;
static tafkeyinfo keysinfo[KEY_CODE_NUM]={0};
void keycodeinit( ENUM_KEY_CODE keycode,uint32_t group,uint32_t pin)
{
volatile tafkeyinfo *pkey =&(keysinfo[keycode]);
pkey->keycode =keycode;
pkey->enable =1;
pkey->group =group;
pkey->pin =pin;
pkey->ishold =0;
pkey->holdchek =0;
pkey->holdtick=0;
pkey->state =KEY_STATE_IDLE;
switch(group)
{
case GPIOA:rcu_periph_clock_enable(RCU_GPIOA);break;
case GPIOB:rcu_periph_clock_enable(RCU_GPIOB);break;
case GPIOC:rcu_periph_clock_enable(RCU_GPIOC);break;
case GPIOD:rcu_periph_clock_enable(RCU_GPIOD);break;
case GPIOE:rcu_periph_clock_enable(RCU_GPIOE);break;
case GPIOF:rcu_periph_clock_enable(RCU_GPIOF);break;
case GPIOG:rcu_periph_clock_enable(RCU_GPIOG);break;
}
gpio_init(GPIOA,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,pin);
}
typedef void (*keycodeevent_cb)(ENUM_KEY_CODE keycode,ENUM_KEY_STARE state);
static void keycodeeventcall(ENUM_KEY_CODE keycode,ENUM_KEY_STARE state)
{if(0==pkeycodecb){return;}
}
void keycodeupdate( ENUM_KEY_CODE keycode)
{
volatile int holdchange=0;
tafkeyinfo *pkey=&(keysinfo[keycode]);
ENUM_KEY_STARE state = pkey->state;
if(!pkey->enable){return;}
pkey->holdchek<<=1;
pkey->holdchek|=gpio_input_bit_get(pkey->group,pkey->pin)?0:1;
if(0==pkey->ishold&&((unsigned long long)-1)==pkey->holdchek)
{
pkey->ishold=1;
holdchange=1;
}
else if(1==pkey->ishold&&0==pkey->holdchek)
{
pkey->ishold=0;
holdchange=-1;
}
switch(state)
{
case KEY_STATE_IDLE:
if(1==holdchange)
{
pkey->state=KEY_STATE_HOLDING;
// pkey.holdtick=
break;
case KEY_STATE_HOLDING:
if(123)
{
pkey->state=KEY_STATE_LONGHOLD;
keycodeeventcall(pkey->keycode,pkey->state);
break;
}
if(123)
{
if(-1==holdchange)
{
pkey->state=KEY_STATE_CLICK;
keycodeeventcall(pkey->keycode,pkey->state);
break;}
else{
pkey->state=KEY_STATE_WAIT_TRIG;
pkey->holdtick=123;
break;
}
break;
case KEY_STATE_WAIT_TRIG:
if(123)
{pkey->state=KEY_STATE_CLICK;
keycodeeventcall(pkey->keycode,pkey->state);
break;
}
if(1==holdchange)
{
pkey->state=KEY_STATE_DBCLICK;
keycodeeventcall(pkey->keycode,pkey->state);
break;
}
break;
case KEY_STATE_CLICK:
pkey->state=KEY_STATE_IDLE;
break;
case KEY_STATE_DBCLICK:
pkey->state=KEY_STATE_IDLE;
break;
case KEY_STATE_LONGHOLD:
if(!pkey->ishold)
pkey->state=KEY_STATE_IDLE;
break;
}
}
}
}
按键消抖有软件和硬件两种方法,这个是软件方法,就是按下去等都是按下去的时候为按下,一但中间有松开则这个过程需要从头开始,双击就是300ms之内再次按下,单机按下小于300ms,长按超过3s,没有超过3s就是单击。