//按键短按加或减,长按连加或连减,四位一体数码管显示0~9999。
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define key_short 10//宏定义短按20ms
#define key_long 50//宏定义长按100ms
#define key_middle 40//宏定义长按间隔80ms
sbit led=P1^4;//启停指示灯
sbit addkey=P3^0;//位定义加键
sbit deckey=P3^2;//位定义减键
sbit qiting=P3^4;//位定义启动按键端口
sbit tingzhi=P3^6;//位定义停止按键端口
//uchar i;//数码管位数变量
uchar flag;//显示函数标志位变量
uchar qitingnum;//声明启停次数变量
uint num;//数值变量
uint addcount,deccount;//计数变量
uint qian,bai,shi,ge;//定义拆字变量
//uchar code weima[]={0xfe,0xfd,0xfb,0xf7};//数码管位码表
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f} ; //共阴数码管段码数字0~9字码表,高电平点亮数码管段码数字0~9。
/**ms级延时子程序**/
void delay(uint x)
{
uint i,j;
for(i=0;i<x;i++)
for(j=0;j<110;j++);
}
void display()
{
qian=num/1000;//转速/10000的余数/1000得到千位
bai=num%1000/100;//取得百位
shi=num%100/10;//取得十位数字
ge=num%10;//取得个位数字
P2=0xfe;//数码管千位显示位
P0=table[qian];//数码管千位数值显示
delay(2);//延时
P2=0xfd;//数码管百位显示位
P0=table[bai];//数码管百位数值显示
delay(2);//延时
P2=0xfb;//数码管十位显示位
P0=table[shi];//数码管十位数值显示
delay(2);//延时
P2=0xf7;//数码管个位显示位
P0=table[ge];//数码管个位数值显示
delay(2);//延时
}
void qidongkeyscan()//启动函数
{
if(qiting==0)
{
delay(15);
if(qiting==0)
{
qitingnum++;
TR0=1;
flag=0;
while(qiting==1);
}
}
}
void tingzhikeyscan()//关掉函数
{
if(tingzhi==0)
{
delay(15);
if(tingzhi==0)
{
led=1;
flag=1;
TR0=0;
P2=0xff;
P0=0x00;
qitingnum=0;
while(tingzhi==1);
}
}
}
void keyscan()//设置函数
{
if(qitingnum==1)
{
led=0;
if(!addkey)
{
addcount++;
// delay(10);
if(addcount>=key_long)//增加长按
{
if(num<9999)
num++;
addcount=key_middle;//为什么存在addcount=key_middle,由于一直按着按键,addcount计数会溢出,设定addcount=key_middle能让addcount在这个addcount=key_middle基础上反复累积计数,从而不会出现计数溢出的情况。
}
}
else
{
if(key_short<addcount&&addcount<key_long)//增加短按,为什么不可以是key_short<addcount<key_long,假若是key_short<addcount<key_long,就相当于按键还没按下,条件已经满足,按键再按下去就没意义啦。
{
if(num<9999)
num++;
}
addcount=0;
}
if(!deckey)
{
deccount++;
// delay(10);
if(deccount>=key_long)//减少长按
{
if(num>0)
num--;
deccount=key_middle;//为什么存在deccount=key_middle,由于一直按着按键,deccount计数会溢出,设定deccount=key_middle能让addcount在这个deccount=key_middle基础上反复累积计数,从而不会出现计数溢出的情况。
}
}
else
{
if(key_short<deccount&&deccount<key_long)//减少短按,为什么if条件不可以是key_short<deccount<key_long,假若是key_short<deccount<key_long,就相当于按键还没按下,条件已经满足,按键再按下去就没意义啦。
{
if(num>0)
num--;
}
deccount=0;
}
}
}
// void display()//显示程序
//{
//// static uchar i;
// P0=0x00;
// P2=weima[i];
// switch(i)
// {
// case 0:
// P0=table[num/1000];
// break;
// case 1:
// P0=table[num%1000/100];
// break;
// case 2:
// P0=table[num%100/10];
// break;
// case 3:
// P0=table[num%10];
// break;
// }
// i++;
// i%=4;
// }
/**定时器0初始化子程序**/
void Time0_init()
{
TMOD=0X01;//模式选定时器0、计数器1,工作方式选定时器0定时模式1、计数器1计数模式1。
TH0=(65536-5000)/256;//定时器0高8位定时50毫秒
TL0=(65536-5000)%256;//定时器0低8位定时50毫秒
EA=1;//打开总中断
ET0=1;//打开定时器0的中断
TR0=0;//打开定时器0
}
void Timer0() interrupt 1//定时器0中断子程序
{
TH0=(65536-5000)/256;//重装定时器0高8位定时50毫秒
TL0=(65536-5000)%256;//重装定时器0低8位定时50毫秒
keyscan();//设置函数
if(flag==0)
display();//显示函数
tingzhikeyscan();//关掉函数
}
void main()//主函数
{
Time0_init();//定时器0初始化子程序
while(1)
{
qidongkeyscan();//启动函数
}
}