51单片机—按键判定(单击,双击,按键更新函数)

目录

一,使用delay直接大致跳过抖动的那段周期

二,找两个按键电平降低 前后时刻的电位

三,多次采样 使用数组和char型变量存放判断

按键扫描函数

单个按键扫描函数

双按键按下的扫描函数

通过定时器的控制即可实现另一种双按键判定

按键动作函数

按键更新函数

两个按键的按键更新

三个按键的按键更新

结语


当按键按下的时候是有电平抖动的,所以有以下三种解决方案

一,使用delay直接大致跳过抖动的那段周期

unsigned char Key()
{
	unsigned char KeyNumber=0;
	if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
	if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
	if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
	if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}

	return KeyNumber;
}

二,找两个按键电平降低 前后时刻的电位

较为简单,不做示例

三,多次采样 使用数组和char型变量存放判断

按键扫描函数

单个按键扫描函数

通过判断第i个数组的数值来判断i对应的按键是否被按下

//单个按键扫描函数
unsigned char key_scan()
{
	unsigned char i;
    unsigned char key_value=0;
	static unsigned char pre_sta[2]={1,1};

    for(i=0;i<2;i++)//2代表能扫描两个按键
	 {
		 if(cur_sta[i]!=pre_sta[i])
		{
			if(pre_sta[i])
			{
			  key_value=i+1;// 按键值
			}
			pre_sta[i]=cur_sta[i];// 更新前一个数组的状态
		} 
  }
	return(key_value);
}

双按键按下的扫描函数

思路:当进入第二个按键的判定时,倘若第一个按键正处于按下的状态,则视为两个按键同时按下,倘若此时第一个按键并不是按下的状态,则正常判断按键按下。

简单来说就是类似于ctrl+c/v的操作逻辑

unsigned char key_scan()
{
	char i;
    char key_value=0;
	
	//判断两个按键是否同时按下
	for(i=0;i<2;i++)
	{
	 if(pre_sta[i]!=cur_sta[i])
	 {
	  if(pre_sta[i])
		{
			 if(i==1 && cur_sta[0]==0) //当第二个按键按下时,第一个按键也正好处于按下状态
		     key_value=3;
		else
		 { 
			 key_value=i+1;
		 }
		}
		pre_sta[i]=cur_sta[i];// 状态更新
	 }
	}
	return(key_value);
}

通过定时器的控制即可实现另一种双按键判定

#include <REGX52.H>
#include "Timer0.h"


#define X 2 //X按键双击

static unsigned char currentkeynum;
static unsigned char lastkeynum;
static unsigned int lasttime=0;
static unsigned int currenttime=0;
static unsigned int timecounter;


void doubleclick_init(void)//初始化双击判断
{
    lastkeynum=0;
    lasttime=0;
		Timer0_Init();//初始化定时器
}

unsigned char check(unsigned char currentkeynum)
{
	
	if(currentkeynum==X && lastkeynum!=X)//判断第一次按按键
	{
		lasttime=timecounter;
		lastkeynum=currentkeynum;
		return 0;//提前返回,第二次输入按键再重新处理
	}
	
	if(lastkeynum==X && currentkeynum==X)//判断第二次按按键
	{
		currenttime=timecounter;
		if(currenttime-lasttime>0 && currenttime-lasttime<1000)//判断两次按键的时间间隔是否为连击
		{
			lastkeynum=0;//重置上次键值
			return 1;//满足双击条件
		}
		else//不满足连续两次按按键就重新初始化
		{
			lastkeynum=0;
			lasttime=0;
		}
	}
	return 0;
}
void Timer0_Routine() interrupt 1
{
		TL0 = 0x66;				//设置定时初始值
		TH0 = 0xFC;				//设置定时初始值
		timecounter++;
		if(timecounter>=10000)
		{
			timecounter=0;
		}
		
}

按键动作函数

一般要根据实际场景进行定制使用

void key_action(unsigned char key_value)

按键更新函数

根据按键个数进行相应的调整

两个按键的按键更新

void cur_sta_update()
{
	unsigned char i;
	static unsigned char buff[2]={0xff,0xff};

    //八次更新状态,要是按键对应的八位都为1则是按下
    buff[0]=(buff[0]<<1)|k1;
	buff[1]=(buff[1]<<1)|k2;
    
    //遍历两个按键
	for(i=0;i<2;i++)
	{
	if(buff[i]==0xff)
		cur_sta[i]=1;
	else if(buff[i]==0x00)
		cur_sta[i]=0;
  }
}

三个按键的按键更新

void cur_sta_update()
{
	char i;
  static unsigned char keybuff[3]={0xff,0xff,0xff};
  
	//八次更新状态,要是按键对应的八位都为1则是按下
	keybuff[0]=(keybuff[0]<<1)|k1;
  keybuff[1]=(keybuff[1]<<1)|k2;
  keybuff[2]=(keybuff[2]<<1)|k3;
	
	//遍历三个按键
  for(i=0;i<3;i++)
 {
  if(keybuff[i]==0xff)
		cur_sta[i]=1;
	else if(keybuff[i]==0x00)
		cur_sta[i]=0;
 }
}

按键的定时器

void timer_2ms() interrupt 1
{
	static unsigned int sec_count=0;
    TH0=(65536-2000)/256;
    TL0=(65536-2000)%256;
	sec_count++;
	if(Turn_on)
	{
	if(sec_count==500) //1 sec 
	{
		
		sec_count=0;
	    DisplayCode_update_time();

	}
  }
  cur_sta_update();
}

结语

按键的扫描和判定都可以直接封装成函数,难点在于key_action函数怎么写,怎么去根据实际的任务需求去调整代码逻辑和时序安排

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值