一、原理图
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPB9EMZpXTwEkaOBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL3EDN0MjMxATM5EzNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
二、独立按键电路分析
J5跳帽接23,即BTN,实现独立按键功能。
当独立按键中有键按下时,P30~P33中对应的IO口变为低电平0,即可确认是哪个按键按下。
三、代码实现
状态机消抖
每隔10ms调用该函数,配合定时器使用。
#define KEY P3
#define key_state_0 0 //判断按键是否按下
#define key_state_1 1 //判断按键是否抖动
#define key_state_2 2 //判断按键是否释放
状态机消抖
unsigned char scan_key()
{
static char key_state=0;//状态值
unsigned char key_return=0;//返回值
unsigned char key_press;//键值
key_press=KEY&0x0f;//屏蔽高四位
switch (key_state)
{
case key_state_0:
if (key_press!=0x0f)
key_state=key_state_1;
break;
case key_state_1:
if (key_press!=0x0f)
{
switch (key_press)
{
case 0x07:
key_return=4;break;//S4
case 0x0b:
key_return=5;break;//S5
case 0x0d:
key_return=6;break;//S6
case 0x0e:
key_return=7;break;//S7
}
key_state=key_state_2;
}
else
key_state=key_state_0;
break;
case key_state_2:
if (key_press==0x0f)
key_state=key_state_0;
break;
}
return key_return;
}
三行代码
每隔10ms调用该函数,配合定时器使用。
#define KEY P3
unsigned char Trg;//判断哪个按键按下
unsigned char Cont;//判断按键是否释放
//三行代码
void scan_key()
{
unsigned char ReadData=KEY^0xff;//^异或 相同为0 不同为1
Trg=ReadData&(ReadData^Cont);
Cont=ReadData;
}
四个独立按键按键数字显示在数码管上 状态机消抖 定时器中断实现
#include <STC15F2K60S2.h>
#define KEY P3
#define key_state_0 0 //判断按键是否按下
#define key_state_1 1 //判断按键是否抖动
#define key_state_2 2 //判断按键是否释放
unsigned char scan_key();//按键扫描函数
void display();//显示函数
void Timer0Init(void);//定时器
code unsigned char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};//共阳数码管段码
unsigned char dspbuf[8]={11,11,11,11,11,11,11,0};//显示缓冲区
unsigned char dspcom=0;
unsigned char key_flag;//消抖标志
//主函数
void main()
{
unsigned char x;
Timer0Init();
EA=1;
ET0=1;
while(1)
{
if (key_flag==1)
{
key_flag=0;
x=scan_key();
if (x==4)
dspbuf[7]=x;
if (x==5)
dspbuf[7]=x;
if (x==6)
dspbuf[7]=x;
if (x==7)
dspbuf[7]=x;
}
}
}
//定时器
void Timer0Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
//中断服务函数
void isr_timer_0() interrupt 1
{
static unsigned char count=0;
count++;
if (count==10)//10ms
{
count=0;
key_flag=1;
}
display();
}
//按键扫描函数
unsigned char scan_key()
{
static char key_state=0;//状态值
unsigned char key_return=0;//返回值
unsigned char key_press;//键值
key_press=KEY&0x0f;//屏蔽高四位
switch (key_state)
{
case key_state_0:
if (key_press!=0x0f)
key_state=key_state_1;
break;
case key_state_1:
if (key_press!=0x0f)
{
switch (key_press)
{
case 0x07:
key_return=4;break;//S4
case 0x0b:
key_return=5;break;//S5
case 0x0d:
key_return=6;break;//S6
case 0x0e:
key_return=7;break;//S7
}
key_state=key_state_2;
}
else
key_state=key_state_0;
break;
case key_state_2:
if (key_press==0x0f)
key_state=key_state_0;
break;
}
return key_return;
}
//显示函数
void display()
{
//消隐
P2=((P2&0x1f)|0xe0);
P0=0xff;
P2&=0x1f;
//位选
P2=((P2&0x1f)|0xc0);
P0=(1<<dspcom);
P2&=0x1f;
//段选
P2=((P2&0x1f)|0xe0);
P0=tab[dspbuf[dspcom]];
P2&=0x1f;
if (++dspcom==8)
dspcom=0;
}
四个独立按键按键数字显示在数码管上 三行代码法 定时器中断实现
#include <STC15F2K60S2.h>
#define KEY P3
void scan_key();//按键扫描函数
void display();//显示函数
void Timer0Init(void);//定时器
code unsigned char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};//共阳数码管段码
unsigned char dspbuf[8]={11,11,11,11,11,11,11,0};//显示缓冲区
unsigned char dspcom=0;
unsigned char key_flag;//消抖标志
unsigned char Trg;//判断哪个按键按下
unsigned char Cont;//判断按键是否释放
//主函数
void main()
{
Timer0Init();
EA=1;
ET0=1;
while(1)
{
if (key_flag==1)
{
key_flag=0;
scan_key();
if (Trg&0x08)
dspbuf[7]=4;//S4
if (Trg&0x04)
dspbuf[7]=5;//S5
if (Trg&0x02)
dspbuf[7]=6;//S6
if (Trg&0x01)
dspbuf[7]=7;//S7
}
}
}
//定时器
void Timer0Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
//中断服务函数
void isr_timer_0() interrupt 1
{
static unsigned char count=0;
count++;
if (count==10)//10ms
{
count=0;
key_flag=1;
}
display();
}
//三行代码
void scan_key()
{
unsigned char ReadData=KEY^0xff;
Trg=ReadData&(ReadData^Cont);
Cont=ReadData;
}
//显示函数
void display()
{
//消隐
P2=((P2&0x1f)|0xe0);
P0=0xff;
P2&=0x1f;
//位选
P2=((P2&0x1f)|0xc0);
P0=(1<<dspcom);
P2&=0x1f;
//段选
P2=((P2&0x1f)|0xe0);
P0=tab[dspbuf[dspcom]];
P2&=0x1f;
if (++dspcom==8)
dspcom=0;
}