一、按钮原理图
独立按钮与矩阵按钮的切换只需与板子上跳帽位置有关
KBD为独立按钮,而BTN为矩阵按钮。
独立按钮是由s4、s5、s6、s7组成,由于跳帽J5将2、3相连最左端接地,只需控制最右端为高电平即可连通
二、按钮的特性
通常按键所用的开关都是机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上就稳定的接通,在断开时也不会一下子彻底断开,而是在闭合和断开的瞬间伴随了一连串的抖动,如图所示。
按键稳定闭合时间长短是由操作人员决定的,通常都会在100ms 以上,刻意快速按的话能达到40-
50ms 左右,很难再低了。
抖动时间是由按键的机械特性决定的,一般都会在10ms以内,为了确保程序对按键的一次闭合或者一次断开只响应一次,必须进行按键的消抖处理!
三、按钮的相关编程(消抖)
例题:
每按下一次s4,数码管上的数字+1
可以根据P33的电平消抖
在while(1)内循环
①读取P33状态;
②如果是0,则等待10ms;再读取P33状态;如果不是1,继续读取P33状态;
如果还是0,确定有按键按下;则执行number+;程序,让数码管数字+1:
如果不是0,则说明是抖动,则不执行任何程序!
③等待按键弹起后,再等待10ms,方可从①再开始执行;
(如果不等待,则在循环内1~3会一直执行,让数字疯狂+1)
方法一:
#include <STC15F2K60S2.H>
#define key_no 0
#define key_down 1
#define key_up 2
unsigned char cnt_key=0;
typedef struct
{
unsigned char b0:1;
unsigned char b1:1;
unsigned char b2:1;
unsigned char b3:1;
unsigned char b4:1;
unsigned char b5:1;
unsigned char b6:1;
unsigned char b7:1;
} bits;
typedef union
{
unsigned char hex;
bits b;
} HexToBin;
void vDevice_ctrl(unsigned char P0data,unsigned char P2data)
{
P0=P0data;
P2=P2data;
P2=0;
}
void vsystem_init()
{
vDevice_ctrl(0,0xa0);
}
unsigned char vBTN_read()
{
static unsigned char key_state=0;
unsigned char key_io=0,key_val=0;
key_io=P3&0x0f;
switch(key_state)
{
case key_no:
if(key_io!=0x0f) key_state=key_down;
break;
case key_down:
if(key_io!=0x0f)
{
if(key_io==0x0e)key_val=7;
else if(key_io==0x0d)key_val=6;
else if(key_io==0x0b)key_val=5;
else if(key_io==0x07)key_val=4;
key_state=key_up;
}
else
{
key_state=key_no;
}
break;
case key_up:
if(key_io==0x0f)key_state=key_no;
break;
}
return key_val;
}
unsigned int number=0;
void vBTN()
{
unsigned char key_val;
if(cnt_key>=10)
{
cnt_key=0;
key_val=vBTN_read();
if(key_val==4)number++;
}
}
unsigned char smg_code[10]={ 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
unsigned char smg_buf[8];
void vsmg()
{
smg_buf[0]=smg_code[number/100];
smg_buf[1]=smg_code[number/10%10];
smg_buf[2]=smg_code[number%10];
smg_buf[3]=0x00;
smg_buf[4]=0x00;
smg_buf[5]=0x00;
smg_buf[6]=0x00;
smg_buf[7]=0x00;
}
void vsmg_display()
{
static unsigned char i=0;
vDevice_ctrl(0,0xc0);
vDevice_ctrl(~smg_buf[i],0xe0);
vDevice_ctrl(0x01<<i,0xc0);
i=(i+1)%8;
}
void Timer2_Init(void) //1??@12.000MHz
{
AUXR |= 0x04; //?????1T??
T2L = 0x20; //???????
T2H = 0xD1; //???????
AUXR |= 0x10; //???2????
IE2 |= 0x04; //????2??
EA = 1;
}
void t2int() interrupt 12 //????
{
cnt_key++;
vsmg_display();
}
void main()
{
vsystem_init();
Timer2_Init();
while(1)
{
vsmg();
vBTN();
}
}
方法二:
#include <STC15F2K60S2.H>
unsigned char Trg;
unsigned char Cont;
void vBTN_Read_TreeLines()
{
unsigned char ReadData=P3^0xff;
Trg=ReadData&(ReadData^Cont);
Cont=ReadData;
}
unsigned char cnt_key=0;
void vSystem_Init()
{
vDevice_ctrl(0,0xa0);
}
unsigned char number=0;
void vBTN_process()
{
if(cnt_key>=10)
{
cnt_key=0;
vBTN_Read_TreeLines();
if(Trg&0x01)number=number-10;
if(Trg&0x02)number=number+10;
if(Trg&0x04)number=number-1;
if(Trg&0x08)number=number+1;
}
}
void vsmg_process()
{
smg_buf[0]=smg_code[number/100];
smg_buf[1]=smg_code[number/10%10];
smg_buf[2]=smg_code[number%10];
smg_buf[3]=0x00;
smg_buf[4]=0x00;
smg_buf[5]=0x00;
smg_buf[6]=0x00;
smg_buf[7]=0x00;
}
void main()
{
vSystem_Init();
Timer2_Init();
while(1)
{
vsmg_process();
vBTN_process();
}
}
void t2int() interrupt 12 //????
{
cnt_key++;
vsmg_display();
}
四、总结
按钮的使用要注意消抖,可以通过对应的P3口的状态来解决