#include <reg51.h>
typedef unsigned char uchar;
typedef unsigned int uint;
void delay(unsigned int i); //函数声名
char DelayCNT;//定义变量
sbit P10=P1^0;
uint Count=0;
uchar n=0;
uchar Key_Value;//获取键盘码
uint i=0;
uint flag=0;
//此表为 LED 的字模, 共阴数码管 0-f
unsigned char code Disp_Tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; //段码控制
//此表为8个数码管位选控制, 共阴数码管 1-8个 -
unsigned char code dispbit[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdF,0xbF,0x7F}; //位选控制 查表的方法控制 从左边开始
//显示缓冲区
uchar led_buf[8]={8,1,2,3,4,5,6,7}; //存放八个数
//计算每一位
void ADcal()
{
led_buf[0]=Count/100;//百位
led_buf[1]=Count/10%10;//十位
led_buf[2]=Count%10;//个位
}
//开时间中断
void initTime(){
IE=0x83;
TR0=1;
}
//开外部中断
void initOut(){
IE=0x83;
IT0=1;
}
//时间中断0
void timer0() interrupt 1
{
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
n++;
if(n==2)
{
P10=1;
delay(20);
P10=0;
delay(20);
Count++;
if(Count>=999)
{
Count=0;
}
}
}
//外部中断0
void out0() interrupt 0
{
Count++;
if(Count>=999)
{
Count=0;
}
}
/**********键盘**************************/
//返回0-15
uchar Keyscan(void)
{
uchar i,j, temp, Buffer[4] = {0xfe, 0xfd, 0xfb, 0xf7};//让矩阵键盘的每行分别为低电平
for(j=0; j<4; j++)
{
P1 = Buffer[j];
temp = 0x10;
for(i=0; i<4; i++)
{
if(!(P1 & temp)) //判断P1口高4位某一行为低电平
{
return (i+j*4);//返回键码
}
temp <<= 1;
}
}
}
uint Key()
{
P1 = 0xf0;
if(P1 != 0xf0)//判断有无按键按下
{
delay(10);//按键消抖
if(P1 != 0xf0)//第二次判断有无按键按下
{
delay(10); //按键消抖
if(P1 != 0xf0)//第三次判断有无按键按下
{
Key_Value = Keyscan();
if(flag == 1)
return 0;
else
return 1;
}
}
}
flag = 0;
return 0;
}
/****************************************/
//将数组中的数右移
void Mov()
{
uint j=7;
for(j;j>0;j--)
{
led_buf[j]=led_buf[j-1];
}
}
/************主函数**********************/
main()
{
/*
unsigned int i,LedNumVal=1 ; //变量定义
unsigned int LedOut[10]; //变量定义
DelayCNT=0;
*/
/*
unsigned int i=0;
initOut(); //打开外部中断'
initTime();
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
*/
delay(10);
while(1)
{/*
if(++DelayCNT>=20) //控制数字变化速度
{
DelayCNT=0; //20个扫描周期清零一次
++LedNumVal; //每隔20个扫描周期加一次
}
LedOut[0]=Disp_Tab[LedNumVal%10000/1000];
LedOut[1]=Disp_Tab[LedNumVal%1000/100]|0x80;
LedOut[2]=Disp_Tab[LedNumVal%100/10];
LedOut[3]=Disp_Tab[LedNumVal%10];
LedOut[4]=Disp_Tab[LedNumVal%10000/1000]; //千位
LedOut[5]=Disp_Tab[LedNumVal%1000/100]|0x80; //百位带小数点
LedOut[6]=Disp_Tab[LedNumVal%100/10]; //十位
LedOut[7]=Disp_Tab[LedNumVal%10]; //个位
for( i=0; i<8; i++)
{
P0 = LedOut[i];
P1 = dispbit[i]; //使用查表法进行位选
delay(150); //扫描间隔时间 太长会数码管会有闪烁感
}
*/
//ADcal();
/*
if(i==2)//百位
{
P0=Disp_Tab[led_buf[i]];
}
if(i==1) //十位
{
P0=Disp_Tab[led_buf[i]];
}
if(i==0)//个位
{
P0=Disp_Tab[led_buf[i]];
}
P2=dispbit[i];//将P2连接位选
i++;
i=i%3;
*/
if(Key())
{
Mov();//数组值右移
flag = 1;
led_buf[0]=Key_Value;//将当前值存到数组第一位
}
//P0=Disp_Tab[Key_Value];
P0=Disp_Tab[led_buf[i]]; //数码管段选
P2=dispbit[i];//将P2连接位选
i++;
i=i%8;
if(i==64)
{
i=0;
}
delay(150);
}
}
/*******************延时函数**********************************************/
void delay(unsigned int i)
{
char j;
for(i; i > 0; i--)
for(j = 200; j > 0; j--);
}