上一篇文章中,对按键的拓展程序是基于最简单的程序模板写的;最近对程序模板进行升级之后,对于按键的拓展也有了新的改变,特此记录。

上一篇文章中,将拓展按键的程序写在了按键程序中。经过尝试,模板拓展之后,再将按键的拓展写在按键程序里不太合适,所以这一次将按键拓展程序写在了定时器里,按键程序中,只保留按下之后的标志位,并且恢复松手检测,不再删除。

目录

按键的长按短按

原理:

独立按键的长按短按

矩阵按键的长按短按

按键的组合

独立按键的组合:

矩阵按键的组合:


按键的长按短按

原理:

用按键按下设立标志位,与定时器计时功能结合,按下之后标志位flag改变,开始计时。到了时间之后,就开始运行程序。

对于同一个按键的长按短按,我们可以数一下题目中要求的长按+短按总共按下几次,来决定flag的分支情况的个数。如题目一,总共按下两次,按下标志位flag就要有三种情况(未按下,短按,长按)。

独立按键的长按短按

题目一:短按S7按键,LED1灯亮起;长按S7按键,LED2灯亮起。并且依次循环

#include <STC15F2K60S2.H>

#define uchar unsigned char
#define uint unsigned int 
	
uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uchar Smg_num=0;
uchar Smg[8]={1,8,10,3,6,10,1,1};

uchar flag=0;
uint tt=0;

void Allinit();
void Delayms(uint ms);
void Keyscan();
void Timer2Init(void);		//1毫秒@11.0592MHz
void Timer0Init(void);		//1毫秒@11.0592MHz

void main()
{
	Allinit();
	Timer0Init();
	Timer2Init();
	while(1)
	{
		
		Keyscan();		
		//Delayms(5);	
	}
}

void timer2() interrupt 12
{
	P2|=0XC0;
	P2&=0XDF;
	P0=(1<<Smg_num);
	P2|=0XE0;
	P2&=0XFF;
	P0=tab[Smg[Smg_num]];
	if(++Smg_num==8)Smg_num=0;
}

void Timer2Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x04;		//定时器时钟1T模式
	T2L = 0xCD;		//设置定时初始值
	T2H = 0xD4;		//设置定时初始值
	AUXR |= 0x10;		//定时器2开始计时

	IE2|=0X04;
	EA=1;
}
void Keyscan()
{
	if(P30==0)
	{
		Delayms(5);
		if(P30==0)//按下
		{
			if(flag==0){flag=1;}//未按下 到 短按
			else if(flag==1){flag=2;}//短按 到 长按
			else if(flag==2){flag=1;}//长按 到 短按
		}
		while(!P30);//抬手检测
	}	
}

void timer0() interrupt 1
{
	if(flag==1)
	{
		tt++;
		if((tt>500)&&(tt<1000))//短按
		{
			P2=0X80;P0=0XFE;tt=0;
		}
	}	
	if(flag==2)
	{
		tt++;
		if(tt>=5000)//长按
		{
			P2=0X80;P0=0XFD;tt=0;
		}		
	}
}
 
void Timer0Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初始值
	TH0 = 0xD4;		//设置定时初始值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	ET0=1;EA=1;
}

void Allinit()
{
	P2=0XA0;P0=0X00;
	
	P2=0X80;P0=0XFF;
	
	P2=0XC0;P0=0XFF;
	P2=0XE0;P0=0XFF;
}

void Delayms(uint ms)
{
	uint i,j;
	for(i=ms;i>0;i--)
	for(j=845;j>0;j--);
}

题目二:短按S7按键,LED1灯亮起;长按S7按键,LED2灯亮起,再次长按S7按键,LED3灯亮起。并且依次循环。

这个题目就类似于第十二届省赛的第二场比赛中的要求。

代码只写按键和定时器部分。

uchar flag=0;
uint tt=0;

void main()
{
	Allinit();
	Timer0Init();
	Timer2Init();
	while(1)
	{
		
		Keyscan();		
		//Delayms(5);	
	}
}

void Keyscan()
{
	if(P30==0)
	{
		Delayms(5);
		if(P30==0)//按下
		{
			if(flag==0){flag=1;}//第一次按下  未按下 到 短按
			else if(flag==1){flag=2;}//第二次按下   短按 到 第一次长按
			else if(flag==2){flag=3;}//第三次按下   短按 到 第二次长按
			else if(flag==3){flag=1;}//第四次按下   第二次长按 到 短按
		}
		while(!P30);
	}
}

void timer0() interrupt 1
{
	if(flag==1)
	{
		tt++;
		if((tt>500)&&(tt<1000))//短按
		{
			P2=0X80;P0=0XFE;tt=0;
		}
	}	
	else if(flag==2)
	{
		tt++;
		if(tt>=5000)//长按  第一次 
		{
			P2=0X80;P0=0XFD;tt=0;
		}		
	}
	else if(flag==3)
	{
		tt++;
		if(tt>=5000)//长按  第二次 
		{
			P2=0X80;P0=0XFB;tt=0;
		}	
	}
}
 
void Timer0Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初始值
	TH0 = 0xD4;		//设置定时初始值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	ET0=1;EA=1;
}

矩阵按键的长按短按

题目:

短按S15按键,LED1灯亮起;第一次长按S15按键5秒,LED2灯亮起;第二次长按S15按键5秒,LED3灯亮起;
短按S19按键,数码管1显示8;第一次长按S19按键5秒,数码管1显示7;第二次长按S19按键5秒,数码管1显示6。

并且依次循环。

与上面独立按键相同的是,在按键模块的程序里,只涉及按下按键之后标志位flag的改变。定义两个按键的标志位:uchar flag_S15=0,flag_S19=0;

与上面独立按键有所不同的是,矩阵按键在按下的次数上多了一个标志位的判断。

uchar ff=0;//按键S15 按下次数的标志位;uchar gg=0;//按键S19 按下次数的标志位

重点来了:

按下次数的标志位一开始置0,在中断中检测到初次按下之后,该标志位置1;

      然后在主函数中,当检测到该标志位为1时,将其值置2;

      再回到中断中检测到该标志位为2时,将该标志位置3

                然后在主函数中,当检测到该标志位为3时,将其值置4;

                再回到中断中检测到该标志位为4时,将该标志位置5;

                              然后在主函数中,当检测到该标志位为5时,将其值置0;

对于这些标志位还要细细理解。

注意:

对于时间的控制,与独立按键也有所不同。我们要求第一次长按5秒,第二次长按也是5秒;

在中断中检测到短按之后,时间置0;当检测到第一次长按之后,时间要置为5000毫秒;这样在检测第二次长按的时候,判断条件就成了>=10000毫秒。

程序:

#include <STC15F2K60S2.H>

#define uchar unsigned char
#define uint unsigned int 
	
uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uchar Smg_num=0;
uchar Smg[8]={11,11,11,11,11,11,11,11};

uchar flag_S15=0,flag_S19=0;
uint tt_S15=0;tt_S19=0;
uchar ff=0;//按键S15 按下次数的标志位
uchar gg=0;//按键S19 按下次数的标志位

void Allinit();
void Delayms(uint ms);
void Keyscan16();
void Timer2Init(void);		//1毫秒@11.0592MHz
void Timer0Init(void);		//1毫秒@11.0592MHz

void main()
{
	Allinit();
	Timer0Init();
	Timer2Init();
	while(1)
	{
		if(ff==1)ff=2;
		else if(ff==3)ff=4;
		else if(ff==5)ff=0;
		
		if(gg==1)gg=2;
		else if(gg==3)gg=4;
		else if(gg==5)gg=0;
		
		Keyscan16();
		//Delayms(5);	
	}
}

void timer0() interrupt 1
{
	if(flag_S15==1)
	{
		tt_S15++;
		if(((tt_S15>500)&&(tt_S15<1000))&&(ff==0))//短按
		{
			P2=0X80;P0=0XFE;tt_S15=0;ff=1;
		}
	}
	else if((flag_S15==2)&&(ff==2))
	{
		tt_S15++;
		if(tt_S15>5000)//短按 到 第一次长按
		{
			P2=0X80;P0=0XFD;tt_S15=5000;ff=3;
		}
	}
	else if((flag_S15==3)&&(ff==4))
	{
		tt_S15++;
		if(tt_S15>10000)//第一次长按 到 第二次长按
		{
			P2=0X80;P0=0XFB;tt_S15=0;ff=5;
		}
	}
	
	if(flag_S19==1)
	{
		tt_S19++;
		if(((tt_S19>500)&&(tt_S19<1000))&&(gg==0))//短按
		{
			Smg[0]=8;tt_S19=0;gg=1;
		}
	}
	else if((flag_S19==2)&&(gg==2))
	{
		tt_S19++;
		if(tt_S19>5000)//短按 到 第一次长按
		{
			Smg[0]=7;tt_S19=5000;gg=3;
		}
	}
	else if((flag_S19==3)&&(gg==4))
	{
		tt_S19++;
		if(tt_S19>10000)//第一次长按 到 第二次长按
		{
			Smg[0]=6;tt_S19=0;gg=5;
		}
	}
}

void Keyscan16()
{
	uchar temp;

	P3=0XDF;P42=1;P44=1;
	temp=P3;
	temp=temp&0X0F;
	if(temp!=0X0F)
	{
		Delayms(5);
		temp=P3;
		temp=temp&0X0F;
		if(temp!=0X0F)
		{
			temp=P3;
			if(temp==0XDE)//S15
			{
				if(flag_S15==0){flag_S15=1;}
				else if(flag_S15==1){flag_S15=2;}				
				else if(flag_S15==2){flag_S15=3;}
				else if(flag_S15==3){flag_S15=1;}
			}
			while(temp!=0X0F)
			{
				temp=P3;
				temp=temp&0X0F;
			}
		}
	}

	P3=0XEF;P42=1;P44=1;
	temp=P3;
	temp=temp&0X0F;
	if(temp!=0X0F)
	{
		Delayms(5);
		temp=P3;
		temp=temp&0X0F;
		if(temp!=0X0F)
		{
			temp=P3;
			if(temp==0XEE)//S19
			{
				if(flag_S19==0){flag_S19=1;}
				else if(flag_S19==1){flag_S19=2;}				
				else if(flag_S19==2){flag_S19=3;}
				else if(flag_S19==3){flag_S19=1;}
			}
			while(temp==0XEF)
			{
				temp=P3;
				temp=temp&0X0F;
			}
		}
	}	
}

void Allinit()
{
	P2=0XA0;P0=0X00;
	
	P2=0X80;P0=0XFF;
	
	P2=0XC0;P0=0XFF;
	P2=0XE0;P0=0XFF;
}

void Delayms(uint ms)
{
	uint i,j;
	for(i=ms;i>0;i--)
	for(j=845;j>0;j--);
}

void Timer0Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初始值
	TH0 = 0xD4;		//设置定时初始值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	ET0=1;EA=1;
}

void timer2() interrupt 12
{
	P2|=0XC0;
	P2&=0XDF;
	P0=(1<<Smg_num);
	P2|=0XE0;
	P2&=0XFF;
	P0=tab[Smg[Smg_num]];
	if(++Smg_num==8)Smg_num=0;
}

void Timer2Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x04;		//定时器时钟1T模式
	T2L = 0xCD;		//设置定时初始值
	T2H = 0xD4;		//设置定时初始值
	AUXR |= 0x10;		//定时器2开始计时

	IE2|=0X04;
	EA=1;
}

按键的组合

独立按键的组合:

题目:

按下S7和S6按键,数码管6显示数字6;按下S5和S4按键,LED1 亮起;

按下S5和S6按键,LED2 亮起;单独按下4个按键,数码管1,2,3,4分别显示1,2,3,4。

组合按键与原来的模板相同,重新写一个组合按键的程序即可。

值得注意的是:再主函数while循环内运行完这个组合按键的程序之后,要加一个200毫秒的延时。否则组合按键和单独按键分别实现的功能无法区分开来。

程序:

#include <STC15F2K60S2.H>

#define uchar unsigned char
#define uint unsigned int 
	
uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uchar Smg_num=0;
uchar Smg[8]={10,10,10,10,10,10,10,10};

void Allinit();
void Delayms(uint ms);
void Keyscan_zuhe();
void Timer2Init(void);		//1毫秒@11.0592MHz

void main()
{
	Allinit();
	Timer2Init();
	while(1)
	{
		Keyscan_zuhe();
		Delayms(200);	
	}
}

void Keyscan_zuhe()
{
 if(P30==0)//按下S7和S6按键,数码管6显示数字6;
	{
		Delayms(5);//延时1秒。两个按键按下的时间差,要小于这个延时,否则判断为单个按键按下
		if(P30==0)
		{
			if(P31==0)
			{
				Smg[5]=6;//两个按键同时按下的程序
			}
			else //只有S7被按下的程序
			{
				Smg[0]=1;
			}
		}
	}	
	
 else if(P32==0)//按下S5和S4按键,LED1 亮起;
	{
		Delayms(5);//延时1秒。两个按键按下的时间差,要小于这个延时,否则判断为单个按键按下
		if(P32==0)//按下S5
		{
			if(P33==0)
			{
				P2=0X80;P0=0XFE;
			}
			else //只有S5被按下的程序
			{
				Smg[2]=3;
			}
		}
	}

 else if(P31==0)//按下S5和S6按键,LED2 亮起
	{
		Delayms(5);//延时1秒。两个按键按下的时间差,要小于这个延时,否则判断为单个按键按下
		if(P31==0)//按下S5
		{
			if(P32==0)
			{
				P2=0X80;P0=0XFD;
			}
			else //只有S6被按下的程序
			{
				Smg[1]=2;
			}
		}
	}	
	
 else if(P33==0)
	{
		Delayms(5);//延时1秒。两个按键按下的时间差,要小于这个延时,否则判断为单个按键按下
		if(P33==0)//按下S4
		{
			if(P33==0)
			{
				Smg[3]=4;
			}
			while(!P34);
		}
	}	
}

void Allinit()
{
	P2=0XA0;P0=0X00;
	
	P2=0X80;P0=0XFF;
	
	P2=0XC0;P0=0XFF;
	P2=0XE0;P0=0XFF;
}

void Delayms(uint ms)
{
	uint i,j;
	for(i=ms;i>0;i--)
	for(j=845;j>0;j--);
}

void timer2() interrupt 12
{
	P2|=0XC0;
	P2&=0XDF;
	P0=(1<<Smg_num);
	P2|=0XE0;
	P2&=0XFF;
	P0=tab[Smg[Smg_num]];
	if(++Smg_num==8)Smg_num=0;
}

void Timer2Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x04;		//定时器时钟1T模式
	T2L = 0xCD;		//设置定时初始值
	T2H = 0xD4;		//设置定时初始值
	AUXR |= 0x10;		//定时器2开始计时

	IE2|=0X04;
	EA=1;
}

矩阵按键的组合:

题目:

按下S15和S14按键,数码管5显示数字5;

按下S19和S18按键,LED1 亮起;按下S18和S17按键,LED2 亮起。

这里要对每一列进行单独控制,比如用到第三列:P35置0,其他列置1.

while循环内200也要进行200毫秒的延时。

其他的与独立按键的原理相同。

程序:

#include <STC15F2K60S2.H>

#define uchar unsigned char
#define uint unsigned int 
	
uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uchar Smg_num=0;
uchar Smg[8]={1,8,10,3,6,10,1,1};

void Allinit();
void Delayms(uint ms);
void Keyscan16();
void Timer2Init(void);		//1毫秒@11.0592MHz

void main()
{
	Allinit();
	Timer2Init();
	while(1)
	{
		Keyscan16();
		Delayms(200);	
	}
}

void Keyscan16()
{
	P35=0;P42=1;P44=1;P34=1;//P35置0
	//按下S15和S14按键,数码管5显示数字5
	if(P30==0)
	{
		Delayms(5);
		if(P30==0)
		{
			if(P31==0)
			{
				Smg[4]=5;
			}
			else 
			{
				Smg[5]=6;
			}
		}
	}

	P35=1;P42=1;P44=1;P34=0;//P34置0
	//按下S19和S18按键,LED1 亮起;
	//按下S18和S17按键,LED2 亮起
	if(P30==0)
	{
		Delayms(5);
		if(P30==0)
		{
			if(P31==0)
			{
				P2=0X80;P0=0XFE;
			}
		}
	}
	else if(P31==0)
	{
		Delayms(5);
		if(P31==0)
		{
			if(P32==0)
			{
				P2=0X80;P0=0XFD;
			}
		}
	}
}

void Allinit()
{
	P2=0XA0;P0=0X00;
	
	P2=0X80;P0=0XFF;
	
	P2=0XC0;P0=0XFF;
	P2=0XE0;P0=0XFF;
}

void Delayms(uint ms)
{
	uint i,j;
	for(i=ms;i>0;i--)
	for(j=845;j>0;j--);
}

void timer2() interrupt 12
{
	P2|=0XC0;
	P2&=0XDF;
	P0=(1<<Smg_num);
	P2|=0XE0;
	P2&=0XFF;
	P0=tab[Smg[Smg_num]];
	if(++Smg_num==8)Smg_num=0;
}

void Timer2Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x04;		//定时器时钟1T模式
	T2L = 0xCD;		//设置定时初始值
	T2H = 0xD4;		//设置定时初始值
	AUXR |= 0x10;		//定时器2开始计时

	IE2|=0X04;
	EA=1;
}

上一篇文章:https://blog.csdn.net/ChenWenHaoHaoHao/article/details/123856564?spm=1001.2014.3001.5501 

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐