按键的拓展:长按短按、组合按键(1)
上一篇文章中,对按键的拓展程序是基于最简单的程序模板写的;最近对程序模板进行升级之后,对于按键的拓展也有了新的改变,特此记录。
上一篇文章中,对按键的拓展程序是基于最简单的程序模板写的;最近对程序模板进行升级之后,对于按键的拓展也有了新的改变,特此记录。
上一篇文章中,将拓展按键的程序写在了按键程序中。经过尝试,模板拓展之后,再将按键的拓展写在按键程序里不太合适,所以这一次将按键拓展程序写在了定时器里,按键程序中,只保留按下之后的标志位,并且恢复松手检测,不再删除。
目录
按键的长按短按
原理:
用按键按下设立标志位,与定时器计时功能结合,按下之后标志位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
更多推荐
所有评论(0)