//功能：检测4*4键盘的按键0~15，然后通过数码管显示出来。
/**************************头文件**************************/
#include "regx52.h"
#define uchar unsigned char
#define uint unsigned int

uchar code dispcode[]={0x3f,0x06,0x5b,0x4f,0x66,
						0x6d,0x7d,0x07,0x7f,0x6f};  //0~9共阴显示子码
uchar code dispbit[]={0xfd,0xfb,0xf7,0xef};			
							//数码管位选码，低电平为选通。分别P11 P12 P13 P14

uchar dispbuf[]="  ";						//个位十位缓冲区
/****************************全局变量 ***************************/
uchar num=0;					 					
bit display_time_5ms_ok=0;

/**************************消抖延时函数	**************************/
void delayms(uchar ms)
{
    uchar b;
	while(ms--)
	{
		for(b=0;b<125;b++);
	}
}

/**************************键盘扫描函数**************************/
void keyboard()				// 扫描键值 （线翻转法）
{  
	uchar keybuf0;
	uchar keybuf1;
	P3=0x0F;
	if(P3!=0x0F)			//初值0x0F，如果有键按下则会变化
	{
		delayms(10);		   	
		P3=0x0F;	
		if(P3!=0x0F)        //消抖
		{																		 
   			keybuf0=P3;										 
			P3=0xF0;										 
			keybuf1=P3;
			keybuf1=keybuf1|keybuf0;	//得到键值
			keybuf1=~keybuf1;
			while(P3!=0xF0);			//while消抖，
		 	switch(keybuf1)
			{
			   case 0x11:num=0;break;
			   case 0x21:num=1;break;
			   case 0x41:num=2;break;
			   case 0x81:num=3;break;
			   case 0x12:num=4;break;
			   case 0x22:num=5;break;
			   case 0x42:num=6;break;
			   case 0x82:num=7;break;
			   case 0x14:num=8;break;
			   case 0x24:num=9;break;
			   case 0x44:num=10;break;
			   case 0x84:num=11;break;
			   case 0x18:num=12;break;
			   case 0x28:num=13;break;
			   case 0x48:num=14;break;
			   case 0x88:num=15;break; 			
			}
	 		dispbuf[1]=num/10%10;			//分离十位 放缓冲区dispbuf[]
	 		dispbuf[0]=num/1%10;			//分离个位
		}
  
 	  }

}

/**************************显示函数*************************/
void display()
{
	 static uchar dispcont;
	 P0=dispcode[dispbuf[dispcont]];//送段码
	 P1=dispbit[dispcont];			//送位码   
   	 dispcont++;					//显示位数偏移量++
	 if(dispcont==2)				//满4清0（四位数码管）
	   dispcont=0;
}

/**************************主函数**************************/
main()							//主程序 
{ 
	IE=0x82;
	TMOD=0X01;
	TH0=(65536-5000)/256;		//定时5MS
	TL0=(65536-5000)%256;
	TR0=1;
	while(1)					//大循环 显示键值
	{
		keyboard();				//调用键盘扫描，写在主函数内时，适用于占用时间不多的程序
		if(display_time_5ms_ok)
	 	{
	  		display();	 
	  		display_time_5ms_ok=0;
	 	}
  	}
}

/*************************中断服务程序*************************/
void timetodisplay() interrupt 1
{
	TH0=(65536-5000)/256;		 //定时5MS
	TL0=(65536-5000)%256;
	display_time_5ms_ok=1;
}


