#include <REGX52.H>
#define KeybufSize 16 //键盘缓存大小
unsigned char KeyBuf[KeybufSize]; //键盘缓存数组,先进先出
unsigned char KeybufWp = 0; //缓存写键值
unsigned char KeybufRp = 0; //缓存读键值
unsigned char keyHit(void); //函数判断是否有键按下
unsigned char keyGet(void); //函数取键值
void keyPut(unsigned char ucKeyVal); //
const unsigned char code seg7code[] ={0x3f, 0x06, 0x5b, 0x4f,
0x66, 0x6d,0x7d, 0x07,
0x7f, 0x6f, 0x77,0x7c,
0x39, 0x5e, 0x79, 0x71,0x00}; //seg7 com cathod
unsigned char keyScan(void); //键盘扫描,行列反转法
/*******************************************************************
p1口接7段LED,p2接键盘输入,p2.0~2.3接KEYPAD-SMALLCALC的行a,b,c,d脚
p2.4~2.7接4个列脚 ,单片机AT89C51,晶振频率12MHz
********************************************************************/
void main(void)
{
TMOD = (TMOD & 0XF0) | 0X01; //定时器0,工作方式1
EA = 1; //开中断允许
ET0 = 1;
TH0 = (-20000)>>8; //定时器0计时20ms
TL0 = -20000;
TR0 = 1;
while(1)
{
if(keyHit() != 0) //有键按下,输出显示。
P1 = seg7code[keyGet()];
}
}
/***********************************************************
利用T0内部中断来扫描键盘,20ms扫描一次,如有键按下,扫描键盘,
并存键盘缓存,如果按键松开,再判断有没有键按下。
************************************************************/
void timer0intr(void) interrupt 1
{
static unsigned char sts = 0;
TH0 = (-20000)>>8;
TL0 = -20000;
P2_0 = 1;
switch(sts)
{
case 0: if(keyScan() != 0) //判断有无键按下,有则转入状态1
sts = 1;break;
case 1: if(keyScan() == 0) //如果按错,转回状态0
sts = 0;
else
{
sts = 2;
keyPut(keyScan()); //确认有键按下,转入状态2,并把键号写入缓存
}
break;
case 2: if(keyScan() == 0)
sts = 3; break; //判断按键松开,转入状态3
case 3: if(keyScan() != 0)
sts = 2;
else
sts = 0; //确认按键已经松开,会状态0,否则回状态2,重新判断
break;
}
}
/***********************************************************
行列反转键盘扫描
************************************************************/
unsigned char keyScan( void ) //返回0表示无按键,或无效按键,其它值为按键编码值
{
code unsigned char keyCode[16]=
//0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF
{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 3, 4, 0 };
unsigned char x, y, retVal;
P1=0x0f; //低四位输入,高四位输出0
x=P1&0x0f; //P1输入后,清高四位,作为X值
P1=0xf0; //高四位输入,低四位输出0
y=(P1 >> 4) & 0x0f; //P1输入后移位到低四位,并清高四位,作为Y值
retVal = keyCode[x]*4 + keyCode[y]; //根据本公式倒算按键编码
if( retVal==0 ) return(0);
else return( retVal-4 );
}
unsigned char keyHit(void) //判断是否有键按下。
{
if(KeybufWp == KeybufRp)
return 0;
else return 1;
}
unsigned char keyGet(void) //读取键值
{
unsigned char retVal;//暂存读出键值
while(!keyHit());
retVal = KeyBuf[KeybufRp];
if(++KeybufRp >= KeybufSize)
KeybufRp = 0;
return retVal;
}
void keyPut(unsigned char ucKeyVal)
{
KeyBuf[KeybufWp] = ucKeyVal;//键值存入数组
if(++KeybufWp >= KeybufSize)
KeybufWp = 0;
}
哎,问题又来了,突然发现按下键盘之后显示的值完全不对,并且只能按一个键,