消抖思路:按键从识别按下开始,持续一个消抖时间,如果按键继续按下,则判定按键按下,否则按键未按下。总共四个按键,定义如下:`
#define KEY1 0x00
#define KEY2 0x01
#define KEY3 0x02
#define KEY4 0x03`
按键按下的状态定义如下:
#define KEY_DOWN 1 //按键被按下
#define KEY_UP 0 //按键弹起
按键物理层实际读取如下:
/*
函数名:KEYx_Scan
说 明:获取按键KEYx的是否按下
传入参数:keyx -----KEY1
KEY2
KEY3
KEY4
返回值: KEY_DOWN---按键按下
KEY_UP-----按键未按下
*/
uint8_t KEYx_Scan(uint8_t keyx)
{
uint8_t key_status=0;
switch(keyx)
{
case KEY1:
key_status = Read_KEY1();
break;
case KEY2:
key_status = Read_KEY2();
break;
case KEY3:
key_status = Read_KEY3();
break;
case KEY4:
key_status = Read_KEY4();
break;
default:
key_status = 0xff;
break;
}
return key_status;
}
按键的状态分为按下与弹起两种,四个按键映射到一个寄存器中,如下:
typedef struct __KEYX
{
uint8_t KEY1_Status:1;
uint8_t KEY2_Status:1;
uint8_t KEY3_Status:1;
uint8_t KEY4_Status:1;
}_KEYX;
extern _KEYX keyx_sta;
#define KEY1_STA keyx_sta.KEY1_Status
#define KEY2_STA keyx_sta.KEY2_Status
#define KEY3_STA keyx_sta.KEY3_Status
#define KEY4_STA keyx_sta.KEY4_Status
然后在一个1ms执行一次的函数中调用KEYx_Scan()函数,同时建立一个数组记录每个按键按下的持续时间。1ms执行一次的函数如下:
#define XD_TIME 20 //消抖时间20ms
#define KEY_NUM 4 //按键数目
void ALLKEY_Scan_1ms(void)
{
static uint8_t xd_time[KEY_NUM];//记录按下的时间
uint8_t i;
for(i=0;i<KEY_NUM;i++)
{
if(KEYx_Scan(i)==KEY_DOWN)
{
xd_time[i]++; //按键i按下,则数组相应++
}
else
{
xd_time[i] = 0; //按键i没有按下,消抖记录时间清0
}
if(xd_time[i]>XD_TIME)
{
Set_Key_Status(i,KEY_DOWN); //如果按键i的消抖时间到
//则将相应按键置按下
}
else
{
Set_Key_Status(i,KEY_UP); //否则,按键没有按下
}
if(xd_time[i]>200)
{
xd_time[i] = 200; //防止溢出
}
}
}
置按键按下与否函数如下:
static void Set_Key_Status(uint8_t keyx,uint8_t key_status)
{
switch(keyx)
{
case KEY1:
KEY1_STA = key_status;
break;
case KEY2:
KEY2_STA = key_status;
break;
case KEY3:
KEY3_STA = key_status;
break;
case KEY4:
KEY4_STA = key_status;
break;
}
}
然后就可以读取按键的状态了,读取函数如下:
uint8_t Read_KEYx(uint8_t keyx)
{
uint8_t key_status;
switch(keyx)
{
case KEY1:
key_status = KEY1_STA;
break;
case KEY2:
key_status = KEY2_STA;
break;
case KEY3:
key_status = KEY3_STA;
break;
case KEY4:
key_status = KEY4_STA;
break;
}
return key_status;
}
在1ms的定时器中执行ALLKEY_Scan_1ms()函数,然后通过Read_KEYx()就可以读取出按键是否被按下。
测试代码如下:
void KEY1_TEST(uint8_t keyx)
{
static uint32_t s_timer=0,cnt_timer=0;
static uint8_t temp;
uint8_t key_value;
if((g_timer-s_timer)>0)
{
s_timer = g_timer;
key_value = Read_KEYx(keyx);
if(key_value == KEY_DOWN)
{
temp = 1;
cnt_timer++;
}
if(temp == 1)
{
if(key_value == KEY_UP)
{
temp = 0;
printf("K%d按下之后又被弹起;cnt_timer=%d\n",keyx+1,cnt_timer);
cnt_timer = 0;
}
}
}
}
测试结果