蓝桥杯学习笔记 单片机CT107D 按键短按,长按,双击的识别

一.原理

实现长按,就是判断按键按下的时间,可以通过计时器实现,简单说就是在按下按键后开始计时,若计时小于一定阈值(如1s)则判定为短按,执行一定的操作,否则判定为长按,执行另一种操作.(如连加操作)

连加操作原理:在若识别为长按,则进入while 循环中判断时间(此处时间是自增的周期,与判断长短按不同,但都是利用计时器,以确保数码管正常显示)同时进行数码管的显示.

双击的实现原理:在检测按键按下的时候置一个标志位,并使其在一个while 中,同时打开定时器定时,如果在一定时间间隔内(如1ms)没有再次检测按键按下,则为单击,如果检测到按下,则为双击,同时为防止第一次按下时进入后面是否双击的判断,可以在前面加入一个循环,按键第一次按下的时候一直处于该循环

碎碎念:在涉及到长按的时候可以不用在扫描之后加上while防止多次触发,因为在读取按下时间的时候可以顺带的防止多次触发

二.练习

1.利用按键S4实现短按加1(若数据>100,则置0),和长按(按键按下时长大于1s)清零的效果.

2利用长按实现连加效果

3实现长按清零,单击加一,双击加五的操作

三.代码实现

1.

#include <REGX52.H>
unsigned char code SMG_NoDot[18]={0xc0,0xf9,
    0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
    0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};//数码管段选表
unsigned char Time_count=0;//按键按下时间
unsigned char Key_Flag=0;计时器开启标志位
unsigned char SMG_data=0;
void DelaySMG(unsigned int t)
{
	while(t--);
}
void Select_HC573(unsigned char channel,unsigned char dat)//573选择
{
	switch(channel)
	{
		case 4:
			P2=(P2&0x1f)|0x80;
		break;
		case 5:
			P2=(P2&0x1f)|0xa0;
		break;
		case 6:
			P2=(P2&0x1f)|0xC0;
		break;
		case 7:
			P2=(P2&0x1f)|0xe0;
		break;
	}
	P0=dat;
	P2=(P2&0x1f)|0x00;
}
void SMG_ShowBit(unsigned char pos,unsigned char dat)
{
	Select_HC573(6,0x01<<(pos-1));
	Select_HC573(7,dat);
	DelaySMG(500);
	Select_HC573(6,0x01<<(pos-1));
	Select_HC573(7,0xff);
}
void SMG_Dynamic()//数码管动态显示
{
	SMG_ShowBit(1,SMG_NoDot[15]);
	SMG_ShowBit(6,SMG_NoDot[SMG_data/100]);
	SMG_ShowBit(7,SMG_NoDot[(SMG_data/10)%10]);
	SMG_ShowBit(8,SMG_NoDot[SMG_data%10]);
	
}
void ScanKey()
{
	if(P3^2==0)
	{
		DelaySMG(500);
		if(P3_3==0) 
		{
			Time_count=0;//计时清零
			Key_Flag=1;//打开计时标志位
			while(P3_3==0)//松手前不执行操作
			{
				SMG_Dynamic();
			}
			Key_Flag=0;//按键抬起,计时结束
			if(Time_count>=20)// 长按情况
			{
				SMG_data=0;
				Time_count=0;
			}
			else//短按情况
			{			
					SMG_data++;
					if(SMG_data>100)
					{
						SMG_data=0;
					}
				}
			}
		}
}
void Timer0_Init()//定时器初始话
{
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	TMOD=0x01;
	EA=1;
	ET0=1;
	TR0=1;
}
void Timer0Service() interrupt 1//定时器服务函数
{
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	if(Key_Flag==1)
	{
		Time_count++;
	}
}
void Sys_Init()//系统初始化
{
	Timer0_Init();
	Select_HC573(4,0xff);
	Select_HC573(5,0x00);
}
void main()
{
	Sys_Init();
	while(1)
	{
		SMG_Dynamic();
		ScanKey();
	}
}

 2.将 ScanKey替换为下列代码

void ScanKey()
{
	if(P3^2==0)
	{
		DelaySMG(500);
		if(P3_3==0) 
		{
			Time_count=0;
			Key_Flag=1;
			while(P3_3==0)
			{
				SMG_Dynamic();
				if(Time_count>=20)//判断是否为长按
			{
					while(P3_3==0)
					{
						SMG_Dynamic();//在进入自增前仍然保持显示
							if(Time_count>=5)
							{
								SMG_data++;
								Time_count=0;//清零以维持周期
							}
					}
			}
			}
			Time_count=0;
			Key_Flag=0;//判断结束
			if(Time_count<20)
			{			
					SMG_data++;
					if(SMG_data>100)
					{
						SMG_data=0;
					}
				}
			}
		}
}

3.三种模式复合 

#include <STC15F2K60S2.H>
sbit S4=P3^3;
sbit S5=P3^2;
sbit S6=P3^1;
sbit S7=P3^0;
unsigned char times;
unsigned char Key_times;
unsigned char gap_times;
bit gap_Flag=0;
bit Key_Flag=0;
code unsigned char SMG_Nodot[] =
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
void Delay_SMG(unsigned int t)
{
	while(t--);
}
void SelectHC573(unsigned char channel,unsigned char dat)
{
	P0=dat;
	switch(channel)
	{
		case 4:
			P2=(P2&0x1f)|0x80;
		break;
		case 5:
			P2=(P2&0x1f)|0xa0;
		break;
		case 6:
			P2=(P2&0x1f)|0xc0;
		break;
		case 7:
			P2=(P2&0x1f)|0xe0;
		break;
	}
	P2=(P2&0x1f)|0x00;
}
void SMG_Display(unsigned char pos,unsigned char dat)
{
	SelectHC573(6,0x01<<(pos-1));
	SelectHC573(7,dat);
	Delay_SMG(500);
	SelectHC573(6,0x01<<(pos-1));
	SelectHC573(7,0xff);
}
void Displya_Dynamic()
{
	SMG_Display(7,SMG_Nodot[times/10]);
	SMG_Display(8,SMG_Nodot[times%10]);
}
void Timer1Init(void)		//10??@12.000MHz
{
	AUXR &= 0xBF;		//?????12T??
	TMOD &= 0x0F;		//???????
	TL1 = 0xF0;		//??????
	TH1 = 0xD8;		//??????
	TF1 = 0;		//??TF1??
	TR1 = 1;		//???1????
	ET1=1;
	EA=1;
}
void Timer1_Service() interrupt 3
{
	if(Key_Flag==1)
	{
		Key_times++;
	}
	if(gap_Flag==1)
	{
		gap_times++;
	}
}
void Scan_Key()
{
	if(S4==0)
	{
		Delay_SMG(500);
		if(S4==0)
		{
			gap_Flag=0;
			Key_Flag=1;
			while(S4==0)
			{
				Displya_Dynamic();
			}
			Key_Flag=0;
			if(Key_times>100)
			{
				times=0;
			}
			if(Key_times<100)
			{
				gap_Flag=1;
				while(gap_Flag==1)
				{
					Displya_Dynamic();
					if(gap_times>12)
					{
						times++;
						gap_Flag=0;
					}
					if(S4==0&&gap_times<12)
					{
						times+=5;
						gap_Flag=0;
					}
				}
			}
			gap_times=0;
			Key_times=0;
		}
		while(S4==0)
		{
			Displya_Dynamic();
		}
	}
}
void Sys_Init()
{
	SelectHC573(4,0xff);
	SelectHC573(5,0x00);
	Timer1Init();
}
void main()
{
	Sys_Init();
	while(1)
	{
		Displya_Dynamic();
		Scan_Key();
	}
}
四.疑问:

1.在编写代码时候误用P3^3来表示S4程序实现问题,不清楚P3^3与P3_3的区别.

  • 16
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值