STC15W单片机状态机检测按键长按和短按

程序思路来自于网络,感谢大佬的开源,点击我即可跳转原网页
定时器初始化函数:设置单片机的定时器工作模式,用来做按键扫描的延时,代替delay延时,释放单片机的资源,定时器设置为12分频用来兼容传统的8051单片机,方便程序移植,更改头文件即可直接运行。

/*定时器0初始化函数*/
void TimeStart()	   //定时器初始化
{	
	EA = 1;			   //打开总中断
	ET0 = 1;		   //打开定时器0中断
	TR0 = 1;		   //打开定时器0
	TMOD = 0X01;	   //设置定时器0为工作模式1	  16位定时器模式  
	TH0 = 0XED;		   
	TL0 = 0XFF;		   //定时5毫秒
}

按键检测函数:通过定时器去扫描按键的状态,原理都在程序注释里面。
第一步:创建一个局部的静态变量,用来表示按键扫描到哪一个步骤了,变量的初始值为0x00。
第二步:判断按键1是否被按下,如果被按下,就把之前创建的静态变量改为0x01,等待下次计时到后执行消抖。
第三步:定时器定时10毫秒到后调用函数,再次判断按键是否被按下(第二次判断为按键消抖),一、如果按键确实被按下,就开始计数,然后把变量改为0x02,进行下一步判断按键是长按还是短按。二、否则就判断为已经抬起,变量改为0x00。
第三步:定时器定时10毫秒又到后再次调用函数,一、判断这时按键的状态是否为弹起,如果是那么就判断为短按,执行LED1的状态反转一次,将变量改为0x00。二、如果按键按下状态超过250毫秒,那么就执行LED3的状态反转一次,变量改为0x03。
第四步:定时器定时10毫秒又到后再次调用函数,判断按键是否已经松开,如果是,那么就将变量的状态改为0x00。

/*按键1 单击 长按 检测函数*/
void KEYS1()						       //按键1扫描函数
{
	static uchar num = 0;			       //局部静态变量     
	switch(num)						   
	{
		case 0x00: if(KEY_S1 == 0) 	       //判断按键1是否被按下
				   {				    
						num = 0x01;	       //跳转到第二条语句    消抖		
				   }
				   break;		           //跳出循环
		case 0x01: if(KEY_S1 == 0)	       //再次判断按键是否被按下   
				   {
						key_time_s1 = 0;   //开始计数   
						num = 0x02;	       //跳转到第三条语句 	 判断单击或者长按
				   }
				   else 				   //否则判断为毛刺
				   {
				   		num = 0x00;		   //跳转到第一条语句  等待下次触发
				   }
				   break;		           //跳出循环
		case 0x02: if(KEY_S1 == 1)	       //判断是否松手
			       {
						LED1 =~ LED1;      //跳转到第一条语句,等待下次按键按下
						num = 0x00;		   //跳转到第一条语句   判断为单击按键				
				   }	   
				   else if(++key_time_s1 >= 50)	   //如果计时的时间超过250毫秒则判断为长按
				   {
				   		LED3 =~ LED3;			   //执行LED3状态反转一次
						num = 0x03;				   //跳转到第4条语句   松手检测
				   }
				   break;						   //跳出循环
		case 0x03: if(KEY_S1 == 1)				   //如果按键松开
				   {
				   		num = 0x00;				   //跳转到第一条语句   等待下次按键被按下
				   }
				   break;						   //跳出循环
		default:		break;
	}
}

定时器0中断处理函数:
定义一个时间标志位来计算定时器的计时时间。
当定时器0进中断一次标志位就加1,表示计时了5毫秒,如果标志位加到2,就表示10毫秒计时时间到了,然后执行一次按键扫描函数。

/*定时器0中断处理函数*/
void Timer0()interrupt 1
{
	static uchar i;		  //时间标志位   用来计算定时时间
	TH0 = 0XED;			  
	TL0 = 0XFF;			  //定时5毫秒时间到后重新给寄存器赋初始值
	i++;				  //时间标志位加1    加1表示5毫秒1次  两次表示十毫秒到
	if(i == 2)			  //判断10毫秒是否到了
	{
		i = 0;			  //10毫秒时间到,时间标志位清零
		KEYS1();		  //扫描按键1
//		KEYS2();		  //扫描按键2
	}	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值