时基法编程之按键

按键

堵塞式按键消抖

如下是一个最基本的堵塞式按键程序:

	
	sbit K1 = P1^0;
	sbit K1 = P1^1;
	sbit K1 = P1^2;
	sbit K1 = P1^3;
	#define KEY_VALUE_NULL	0X00
	#define KEY_VALUE_1		0X01
	#define KEY_VALUE_1		0X02
	#define KEY_VALUE_1		0X04
	#define KEY_VALUE_1		0X08
	
	void delay_ms(unsigned char xms)
	{
		unsigned char i,j;
		for(i = xms;i > 0;i--){
			for(j = 110;j > 0;j--);	
		}
	}
	unsigned char KeyScan(void)
	{
		unsigned char temp = KEY_VALUE_NULL;
		if(K1 == 0){
			delay_ms(20);
			if(K1 == 0){
				temp = KEY_VALUE_1;
			}
		}
		if(K2 == 0){
			delay_ms(20);
			if(K1 == 0){
				temp = KEY_VALUE_2;
			}
		}
		if(K3 == 0){
			delay_ms(20);
			if(K1 == 0){
				temp = KEY_VALUE_3;
			}
		}
		if(K4 == 0){
			delay_ms(20);
			if(K1 == 0){
				temp = KEY_VALUE_4;
			}
		}
		return temp;
	}
	void main(void)
	{
		unsigned char keyValue = 0;
		while(1)
		{
			keyValue = KeyScan();
			if(keyValue == KEY_VALUE_1){
				//按键1按下执行代码段
			}
			if(keyValue == KEY_VALUE_2){
				//按键2按下执行代码段
			}
			if(keyValue == KEY_VALUE_3){
				//按键3按下执行代码段
			}
			if(keyValue == KEY_VALUE_4){
				//按键4按下执行代码段
			}
		}
	}

该代码具有堵塞式按键的通病,那就是当按键按下后,所有的CPU时间都用来空跑,对于实时性高的任务,这20ms消抖会带来很多灾难性后果。20ms够我们跑很大量级的指令数了。我们怎么不使用delay来完成按键消抖呢?

时基法编程之按键消抖

如下是一个最基本的非堵塞式按键程序:

	
	sbit K1 = P1^0;
	sbit K1 = P1^1;
	sbit K1 = P1^2;
	sbit K1 = P1^3;
	
	#define KEY_VALUE_NULL	0X00
	#define KEY_VALUE_1		0X01
	#define KEY_VALUE_1		0X02
	#define KEY_VALUE_1		0X04
	#define KEY_VALUE_1		0X08
	
	unsigned char keyValue   = 0;//按键键值接口
	unsigned char keyScan1ms = 0;//按键时基驱动接口
	
	//读取按键IO口电平
	unsigned char KeyScan(void)
	{
		unsigned char temp = KEY_VALUE_NULL;
		if(K1 == 0){
			temp = KEY_VALUE_1;
		}
		if(K2 == 0){
			temp = KEY_VALUE_2;
		}
		if(K3 == 0){
			temp = KEY_VALUE_3;
		}
		if(K4 == 0){
			temp = KEY_VALUE_4;
		}
		return temp;
	}
	
	void keyProcess(void)
	{
		static unsigned	char keyLastValue = KEY_VALUE_NULL;//上次键值
		static unsigned char keyNowValue  = KEY_VALUE_NULL;//当前键值
		static unsigned char keyFilterCnt = 0;//消抖计数器
		//时基法编程核心语句
		if(keyScan1ms < 10)return;//按键扫描时基未到10ms,则退出
		keyScan1ms = 0;//千万不能忘记清零时基
		
		keyNowValue = KeyScan();//读取此时IO口电平
		if(keyNowValue != KEY_VALUE_NULL){//按键被按下
			if(keyNowValue != keyLastValue){//此次按键跟上次按键键值不一样
				keyFilterCnt = 0;
			}
			keyFilterCnt++;//消抖核心语句
		}
		else{//按键松开
			//10ms采样一次,松手之前连续3次以上采样到按键按下。
			if(keyFilterCnt > 3){
				keyValue = keyLastValue;
			}
			keyFilterCnt = 0;//清消抖计数器
		}
		keyLastValue = keyNowValue;
	}

	void main(void)
	{
		//定时器初始化....
		while(1)
		{
			keyProcess();
			if(keyValue == KEY_VALUE_1){
				keyValue = 0;//使用后手动清键值
				//按键1被按下执行代码
			}
			//......
			//其它进程...
		}
	}
	//定时器中断1ms
	void Timer0_Interrupt() interrupt 1
	{
	    keyScan1ms ++;
	}

上面代码是一个最基本的非堵塞式按键,仅仅实现按键消抖,但其有非常好的扩展性,诸如组合按键、长按、单双击都可以按照这种方式实现。在此不做细述,留待读者深入体会。

非堵塞式编程的优点是非常显然的,比如将前面文章的流水灯+蜂鸣器鸣叫+LED闪烁等等进程添加进来,程序不会有任何卡顿现象出现。但如果用堵塞式编程,则程序会出现明显的卡顿现象。

但是堵塞式也并不是无可取之处,因其逻辑简单、稳定,它在处理实时性要求不高的场合非常适用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值