使用中断函数进行矩阵按键的扫描,在《手把手教你学51单片机》上面的代码修改了一下。感觉这个代码写的比较好。
#include<stc15f2k60s2.h>#define uchar unsigned charsbit KEY_IN_1 = P4^4;
sbit KEY_IN_2 = P4^2;
sbit KEY_IN_3 = P3^5;
sbit KEY_IN_4 = P3^4;
sbit KEY_OUT_1 = P3^0;
sbit KEY_OUT_2 = P3^1;
sbit KEY_OUT_3 = P3^2;
sbit KEY_OUT_4 = P3^3;uchar code LedChar[]={0xc0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0Xbf,0XFF
};uchar KeySta[4][4]={{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
};void main()
{uchar i,j;uchar backup[4][4]={{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}};P2=0xa0;//1010 0000,U9使能P0=0x00;//关蜂鸣器和继电器P2=0x80;//U6使能,关于LED的锁存器打开P0=0xff;//关闭所有LEDP2=0xc0;//U8使能P0=0xff;//com1-com8数码管位选P2=0xff;//U7锁存器】使能,P0=0xff;//段选EA=1;//总使能开TMOD=0x01;//十六位不可重装载模式,TH0,TL0全用TH0=0xfc;//设定中断时间间隔TL0=0x67;ET0=1;//T0中断允许TR0=1;//启动T0//P0=LedChar[0];while(1){for(i=0;i<4;i++){for(j=0;j<4;j++){if(backup[i][j] != KeySta[i][j])//检测当前的按键状态与上一次按键状态 若满足条件说明有按下或弹起动作{if(backup !=0)//如果上一次是抬起状态 说明是按下动作发生了{P0=LedChar[i*4+j];}backup[i][j] = KeySta[i][j];//把当前值保存}}}}
}void InterruptTime0() interrupt 1
{uchar i;static uchar keyout=0;static uchar keybuf[4][4]={//缓冲 保存最近四次结果{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff}};TH0=0xfc;//重载TL0=0x67;keybuf[keyout][0] = (keybuf[keyout][0]<<1) | KEY_IN_1;keybuf[keyout][1] = (keybuf[keyout][1]<<1) | KEY_IN_2;keybuf[keyout][2] = (keybuf[keyout][2]<<1) | KEY_IN_3;keybuf[keyout][3] = (keybuf[keyout][3]<<1) | KEY_IN_4;for(i=0;i<4;i++){if((keybuf[keyout][i] & 0x0f)==0x00)//单个按键连续四次为0确认按下状态{KeySta[keyout][i]=0;//刷新当前值}else if((keybuf[keyout][i]) & 0x0f ==0x0f)//四次为1 弹起状态{KeySta[keyout][i]=1;//刷新当前值}}keyout++;//扫描换行/列keyout&=0x03;switch(keyout){case 0:KEY_OUT_4 =1;KEY_OUT_1=0;break;case 1:KEY_OUT_1 =1;KEY_OUT_2=0;break;case 2:KEY_OUT_2 =1;KEY_OUT_3=0;break;case 3:KEY_OUT_3 =1;KEY_OUT_4=0;break;default:break;}}