独立按键部分
void BTN()//
{
uchar dat=P3^0xff;
Trg=dat&(dat^Cont);
Cont=dat;
}
因为初始状态 P3=0xff,所以dat =0x00,Trg=0x00 ,因为0与上任何数都是0,Cont=0
假设S4按下P3的状态是0xf7,此时 dat =0x08 ,Trg=0x08,Cont=0x08
如果长按,则 dat =0x08 ,Trg=0x00,Cont=0x08
所以我们可以每10ms就去读一次是否触发,相当于是消抖了。
unsigned char flag;//定义全局变量
void Timer0_Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初始值
TH0 = 0xD4; //设置定时初始值
EA=1;
ET0=1;
TR0 = 1; //定时器0开始计时
}
void Timer0() interrupt 1
{
static unsigned char flag_cnt;
flag_cnt++;
if(flag_cnt==10)
{
flag=1;
flag_cnt=0;
}
}
if(flag)
{
BTN();
flag=0;
if(Trg&0x01)//S7
{
}
else if(Trg&0x02)//S6
{
}
else if(Trg&0x04)//S5
{
}
else if(Trg&0x08)//S4
{
}
}
矩阵键盘部分
在开头定义按键值定义成4*4的矩阵。
uchar code keymap[4][4]={{7,11,15,19},{6,10,14,18},{5,9,13,17},{4,8,12,16}};
uchar Trg=0,Cont=0,flag=0,dat=0,keyvalue=0,key=0;
void KBD()
{
uchar row=0,cloumn=0,i,j;
P3=0x0f;P44=0;P42=0;
row=P3&0x0f;
P3=0xf0;P44=1;P42=1;
if(P44 == 0) cloumn = 0x70;
else if(P42 == 0) cloumn = 0xb0;
else cloumn = P3 & 0xf0;
dat=~(cloumn|row);
Trg=dat&(dat^Cont);
Cont=dat;
if(Trg)
{
for(i = 0; i < 4; i++)
for(j = 0; j < 4; j++)
if(Trg == (0x80 >> j | 0x01 << i))
{
keyvalue = keymap[i][j];
key=keyvalue;
break;
}
}
}
分析:当紫色位置按键被按下时,进入检测的代码时会有以下步骤:
1. 列赋0,行都赋1 即P44、P42、P36、P35为低电平 ,P30-P33都是高电平
2.将P3和0X0F进行“与” 操作,得到具体哪一行被按下
3.列赋1,行都赋0 ,即P44、P42、P36、P35为高电平 ,P30-P33都是低电平
4.判断是哪列被按下, 将值赋给cloumn
三行判断式分析:
第一次:
row =(0000 1101) &(0000 1111) =0000 1101
cloumn = 0xb0
dat = ~(row|cloumn)=~( (1011 0000)| 0000 1101) = 0100 0010 = 0x72
Trg = (0x72) & (0x72^0x00) = 0x72 (异或符号^)
Cont = dat =0x72
第二次(紫色按钮还处于按下状态):
row =(0000 1101) &(0000 1111) =0000 1101
cloumn = 0xb0
dat = ~(row|cloumn)=~( (1011 0000)| 0000 1101) = 0100 0010 = 0x72
Trg = (0x72) & (0x72^0x72) =0x00
Cont = dat =0x72
所以这个三行判断式可以检测长按和短按,通过十毫秒的检测 “延时” ,可以达到检测准确的效果。
void Timer0_Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初始值
TH0 = 0xD4; //设置定时初始值
EA=1;
ET0=1;
TR0 = 1; //定时器0开始计时
}
void Timer0() interrupt 1
{
static unsigned char flag_cnt;
flag_cnt++;
if(flag_cnt==10)
{
flag=1;
flag_cnt=0;
}
}
使用模板如下
if(flag)
{
KBD();
flag=0;
if(key==4) //S4
{
key=0;
}
else if(key==5) //S5
{
key=0;
}
else if(key==9) //S9
{
key=0;
}
else if(key==8) //S8
{
key=0;
}
}