采用4位一体共阳数码管,P0口输出段码,P2口输出位码,P1口接4*4矩阵键盘,最左边2个数码管可以显示按键值0~15,按键0可让最右边数码管显示值加1,按键0可减1,显示值在0-9之间循环。可有效避免按一次按键,按键处理却多次的情况。
#include <reg52.h>
#define uchar unsigned char
uchar segcode[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar bitcode[]={0x01,0x02,0x04,0x08};
uchar key_value,key_re;
uchar temp,row,col;
uchar num=5;
void delay(uchar n)
{
uchar i,j;
for(i=0;i<n;i++)
for(j=0;j<120;j++);
}
void main()
{
while(1)
{
if((P1 == 0x0f)||(P1 == 0xf0))
key_re = 1;//按键已释放
P1 = 0x0f;
if((P1&0x0f) != 0x0f)
{
delay(10);
if((P1&0x0f) != 0x0f)
{
temp = P1&0x0f;
switch(temp)
{
case 0x0e: row = 0; break;
case 0x0d: row = 1; break;
case 0x0b: row = 2; break;
case 0x07: row = 3; break;
default: key_value = 0xff; break;
}
P1 = 0xf0;
temp = P1&0xf0;
switch(temp)
{
case 0xe0: col = 0; break;
case 0xd0: col = 1; break;
case 0xb0: col = 2; break;
case 0x70: col = 3; break;
default: key_value = 0xff; break;
}
key_value = row*4 + col;
if(key_re == 1)
{
if(key_value == 0)
num++;
if(num==10)
num=0;
if(key_value == 1)
num--;
if(num==-1)
num=9;
key_re = 0;
}
}
}
P0 = segcode[key_value/10];
P2 = bitcode[0];
delay(2);
P2 = 0x00;
P0 = segcode[key_value%10];
P2 = bitcode[1];
delay(2);
P2 = 0x00;
P0 = segcode[num];
P2 = bitcode[3];
delay(2);
P2 = 0x00;
}
}
对应的仿真电路图如下。
按键检测流程:先置全行高全列低,然后读取0-3行,如有键按下,则有一行读入后为低,记下行号。然后置全行低全列高,然后读取0-3列,如有键按下,则有一列读入后为低,记下列号。行号*4+列号等于键值。为防止一次按键处理多次,采用了变量key_re,re是release的缩写,当P1读入为0x0f或0xf0时,key_re=1,标识按键已释放,在key_re为1,检测到按键按下时,才处理按键值。按键值处理完后key_re=0,如果按键此时按键没有释放,那么再次检测到按键时,key_re=0,不会执行按键处理。这种方法优于采用延时来处理。