//按键短按加或减,长按连加或连减,四位一体数码管显示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();//启动函数 } }