按键的消抖处理

消抖思路:按键从识别按下开始,持续一个消抖时间,如果按键继续按下,则判定按键按下,否则按键未按下。总共四个按键,定义如下:`

#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;
			}
		}
	}
}

测试结果
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_40831436/article/details/106723771