在CT107D单片机综合训练平台上,首先将J5处的跳帽接到2~3引脚,使按键S4~S7四个按键的另外一端接地从而成为4个独立键盘。在扫描按键的过程中,发现有按键触发信号后,先做去抖动处理,当确认为按键按下时,才进行相应的功能处理。

设计内容:

        1.按下S7后抬起,L1点亮,再次按下S7,L1熄灭;

        2.长按S6,L2点亮,松开,L2熄灭;

        3.双击S5,L3点亮;再次双击S5,L3熄灭;

        4.按下S4,L4点亮,长按S4,L4熄灭。

        设计之前,大家需要思考一下,什么是按键的短按、长按、双击,他们之间有什么联系,又有什么区别,简单点来说,短按就是你按键时长要小于一个时间点,比如你手把按键按下去时长要小于0.5秒,这个时候你可以把这个按键动作称为按键的短按,那相反把手按下按键大于0.5秒的按键动作可以理解为按键的长按,那双击又是什么呢?第一次按键按下后,在一段时间内这个按键又再次被按下,则称为双击,如果第二次按键过了这段时间,则表示未完成双击,当然,这段时间是大家自己定义的,下面就是利用这种思路,笔者写出了设计内容所要求的完整程序。

#include<stc15f2k60s2.h>

#define uchar unsigned char   //定义无符号字符类型uchar
#define uint unsigned int     //定义无符号整型类型uint

void delayms(int ms);          //延时函数
void allinit();                //初始化函数
void keyscan();                //独立按键程序
void Timer0Init(void);		     //1毫秒@12.000MHz	

uchar key_up=1;//按键按松开标志,按下时为0,松开时为1
uchar keytime=0; //按键计时	

uchar S7=0,S6=0,S5=0,key=0,cishu=0;
uint tt=0;
bit fla=0;

void main()//主函数
{
	allinit();                  //初始化函数
	Timer0Init();               //定时器初始化
	while(1)
	{
		keyscan();                //独立按键程序
	}
}
void keyscan()
{
	if(P30==0)       //判断P30是否等于0
	{
		delayms(5);    //延时5ms
		if(P30==0)     //再次判断P30是否等于0 
		{
			if(S7==0){S7=1;P2=0X80;P0&=0XFE;}              //标志位S7,用于判断L1灯亮灭状态,当S7=1时,L1亮
			else if(S7==1){S7=0;P2=0X80;P0|=0X01;}         //标志位S7,用于判断L1灯亮灭状态,当S7=0时,L1灭
		}
		while(!P30);   //如果按键不松开,则一直循环
	}
	else if(P31==0)  //判断P31是否等于0
	{
		delayms(5);    //延时5ms
		if(P31==0)     //再次判断P31是否等于0 
		{
			 S6=1;P2=0X80;P0&=0XFD;     //按键按下则S6置1,L2点亮
		}
	}
	else if((S6==1)&&(P31==1))      //判断按键是否为按下后松开状态
	{
		S6=0;P2=0X80;P0|=0X02;        //S6清零,L2熄灭
	}
	else if(P32==0)  //判断P32是否等于0
	{
		delayms(5);    //延时5ms
		if(P32==0)     //再次判断P32是否等于0 
		{
			if(S5==0)
			{
				S5=1;cishu++;EA=1;ET0=1;tt=0;   //第一次按键按下,S5标志位置1,按键次数+1,打开定时器开始计时
			}
			else if(S5==1)            //判断第二次按键是否按下
			{
				if((tt<=500)&&(cishu==1))   //判断按下时按键是否是在500ms以内按下,并且有过一次2按键按下记录
				{
					if(fla==0){fla=1;P2=0X80;P0&=0XFB;}          //标志位fla,用于判断L3灯亮灭状态,当fla=1时,L3亮
					else if(fla==1){fla=0;P2=0X80;P0|=0X04;}     //标志位fla,用于判断L3灯亮灭状态,当fla=0时,L3灭
					EA=0;ET0=0;tt=0;cishu=0;S5=0;   //关闭定时器,定时器按键时长tt清零,按键次数清零,S5标志位置0
				}
				else
				{
					EA=0;ET0=0;              //如果按键时长间隔大于500ms,则关闭定时器
					tt=0;cishu=0;S5=0;       //按键时长间隔tt清零,按键次数清零,S5标志位清零,便于下次按键记录
				}
			}
		}
		while(!P32);   //如果按键不松开,则一直循环
	}
	else if((key_up==1)&&(P33==0))  //判断按键是否按下
	{
		delayms(5);                   //延时5ms,消抖
		if(P33==0) key_up=0;          //再次判断按键是否按下,key_up清零,说明确实有按键按下
	}
	else if(P33==1)                 //程序为松手检测,所以在P33为1时判断按键状态
	{
		if(key_up==0)                 //判断key_up是否为0
		{
			key_up=1;                   //key_up置1,为下次按键记录做准备	
			if(keytime<50)              //判断按键计时是否小于500ms,即为短按
			{
				keytime=0;                //按键计时清零
				P2=0X80;P0&=0XF7;         //执行短按状态,让L4点亮
			}
			keytime=0;                  //按键计时清零
		}
	}
	if(key_up==0)//如果按键按下则按10ms时间计时
	{
		delayms(10);       //延时10ms
		keytime++;         //keytime++,用于在按键按下时有多少个10ms时间流过,方便判断按键长按短按
		if(keytime>=50)    //如果长按时间大于等于500ms则返回按键长按,在此处设置按键长按时长
		{
			P2=0X80;P0|=0X08; //执行长按状态,让L4熄灭
		}	
	}
}
void Timer0Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x20;		//设置定时初值
	TH0 = 0xD1;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}
void time0() interrupt 1   //定时器0中断
{
	if(++tt==1200);          //定时器0计时
}
void delayms(int ms)//延时函数
{
	uint i,j;
	for(i=ms;i>0;i--)
		for(j=845;j>0;j--);
}
void allinit()//初始化函数
{
	P2=0XA0;P0=0X00;      //关闭蜂鸣器继电器
	P2=0X80;P0=0XFF;      //关闭所有LED灯
	
	P2=0XC0;P0=0XFF;      //选中所有数码管段选
	P2=0XFF;P0=0XFF;      //关闭所有数码管
}

 

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐