#include <STC12C5A60S2.H>
sbit ENLED = P1^1;
sbit KOUT4 = P2^4;
sbit KOUT3 = P2^5;
sbit KOUT2 = P2^6;
sbit KOUT1 = P2^7;//这里我私自把KOUT1234改成改成4321了,至于为什么你们可以自己试试
//这里按照原理图本来应该把P2^0定义为P20的,但是头文件里面已经定义过了,所以就不再定义了,也不找其他标识符来定义了
unsigned char code DsChar[] =
{0xc0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xFF};
//这里真值表多了一个0xFF
unsigned char KeySta[4][4] = {{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}};
unsigned char m = 16;
void main()
{
unsigned char i,j;
unsigned char backup[4][4] = {{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}};
EA = 1;
ENLED = 0;
P22 = 0;
P21 = 0;
P20 = 0;
AUXR = 0x80;
TMOD = 0x01;
TH0 = 0x80;
TL0 = 0x00; //AUXR关闭单片机的12分频,定时1ms
ET0 = 1;
TR0 = 1;
P0 = 0xFF;
while(1)
{
for(i = 0;i<4;i++)
{
for(j = 0;j<4;j++)
{
if(backup[j] != KeySta[j])
{
if(backup[j] == 1)
{
m = i*4+j;
P0 = DsChar[m];
}
backup[j] = KeySta[j];
}
}
}
}//while循环代码的核心思想就是挨个检测按键当前的状态是否和之前的状态一样,如果不一样就说明按键发生变化了,再检测按键之前的状态是按下还是弹起,
//这里判断语句中backup[j] == 1,说明检测到之前按键状态是弹起就改变数码管的值。这里我们可以让backup[j] == 1,那就是按下按键,松手的时候数码管再改变
}
void InterruptTimer0() interrupt 1
{
unsigned char i;
static unsigned char keyout = 0;
static unsigned char keybuf[4][4] =
{
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF}
};
TH0 = 0x80;
TL0 = 0x00;
P0 = 0xFF;
P20 = 1;
P21 = 1;
P22 = 1;
//前面这4行就是增加的内容,先让P0=0xFF,防止改变138输入端后点亮对应的部分(其实也可以不加,因为咱们的板子138的输出端Y7什么也没接)
//拉高P20,21,22的电平,准备读取按键
keybuf[keyout][0] = (keybuf[keyout][0]<<1|P20);
keybuf[keyout][1] = (keybuf[keyout][1]<<1|P21);
keybuf[keyout][2] = (keybuf[keyout][2]<<1|P22);
keybuf[keyout][3] = (keybuf[keyout][3]<<1|P23);//这四行是读取按键的瞬间状态
P22 = 0;
P21 = 0;
P20 = 0;
P0 = DsChar[m];
//前面这4行也是增加的内容,把IO口的电平还原回来,并且再次点亮数码管
for(i=0;i<4;i++)
{
if((keybuf[keyout]&0x0F) == 0x00)
{
KeySta[keyout] = 0;
}
else if((keybuf[keyout]&0x0F) == 0x0F)
{
KeySta[keyout] = 1;
}
}
keyout++;
keyout = keyout & 0x03;
switch(keyout)
{
case 0:KOUT4 = 1;KOUT1 = 0;break;
case 1:KOUT1 = 1;KOUT2 = 0;break;
case 2:KOUT2 = 1;KOUT3 = 0;break;
case 3:KOUT3 = 1;KOUT4 = 0;break;
}
}