蓝桥杯单片机----独立按键的基本控制(长按、短按、双击)
·
在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; //关闭所有数码管
}
更多推荐
已为社区贡献3条内容
所有评论(0)