//功能：基于有限状态机的独立键盘扫描，0~9999手动计数
#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[]={0,0,0,0};

bit keytime_10ms_ok;
bit disptime_5ms_ok;
uint num=0;						//计数变量
uchar dispcont;					//显示位数
sbit key1=P3^0;					//Ka

/************************key1按键扫描函数********************/
void key1scan()
{
	static uchar key1state;	//定义静态变量：按键状态
	switch(key1state)		//判断状态值
	{
		case 0:				//初始状态0
		if(key1==0)			//判断按下了没？
		{
			key1state=1;	//按下了,状态转换为1	                     
	   	}
	  		break;			//跳出内层循环
		case 1:				//为1则10MS前按下了,等于消了抖
		if(key1==0)			//再判断是否还按着
	    {
	   		key1state=2;	//是！ 则改变状态为2 清KETTIME 跳出内层循环			                    	   
	    }
	   	else
		{
			key1state=0;	//如果不是 说明是干扰信号 则改为状态0
		}                    	   
	   		break;			//跳出内层循环 		
		case 2:				//如果状态2，说明前面有键按下
		if(key1==1)			//判断松开了没
		{
			key1state=0;	//状态变为0 返回值1 清TIME 跳出内层循环	
	    	num++;			//NUM++
	    	if(num==10000)	//满10000清0（数码管最大显示9999）
			num=0;
	 		dispbuf[3]=num/1000%10;	//分离千位，放缓冲区dispbuf[]
	 		dispbuf[2]=num/100%10;	//分离百位
	 		dispbuf[1]=num/10%10;	//分离十位
	 		dispbuf[0]=num/1%10;	//分离个位
		}
	  		 break;
	}
}

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

/*********************主函数**********************/
main()
{
 	IE=0x82;
 	TMOD=0x01;
 	TH0=(65536-5000)/256;
 	TL0=(65536-5000)%256;
 	TR0=1;
	while(1)
	{
	  if(keytime_10ms_ok)
	  {
	    key1scan();
	    keytime_10ms_ok=0; 
	  }
	
	
	  if(disptime_5ms_ok)
	  {
	    display();	
	    disptime_5ms_ok=0;
	  } 
		
	}

}

/**************************************定时器0中断服务程序***********************************/
void timer0() interrupt 1
{
 	static uchar time;
 	TH0=(65536-5000)/256;			 //重新赋初值
 	TL0=(65536-5000)%256;
	time++;
 	disptime_5ms_ok=1;
 	if(time==2)
  	{
   		keytime_10ms_ok=1;			//键盘扫描10MS时间到
   		time=0;
  	}
}
