/************************************************************************/ /********按键记数0-99 长按键连续加或者连续减实验******************/ /********按k1键加一,超过一定时间连续加一,加到99后k1在按无效*******/ /********按k2键减一,超过一定时间连续减一,减到00后k2在按无效*******/ /************************************************************************/ /****************宏定义*******************/ #include<reg51.h> #define uchar unsigned char #define uint unsigned int #define SEG P2 //段码 #define DIG P0 //位码 sbit k1=P3^0; //按键加1按钮 sbit k2=P3^1; //按键减1按钮 uchar code SegTabl[11] = {0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09,0xff}; uchar DispData[8] = {10,10,10,10,10,10,0,0}; uchar count; //记数 uchar IntCount; //中断记数 uchar keyk1; //k1按下后等待的时间 uchar keyk2; //k2按下后等待的时间 void delay(uint); //延时函数 void key(void); //按键判断函数 void display(void); //扫描显示函数 /****************主程序********************/ void main(void) { //**************硬件初始化*********** //* 使用定时器T0,定时模式,工作方式1;晶振频率f=22.1184MHz-即1S钟有22118400个`````` //晶振脉冲,也就是22118400/12=1843200个机器周期-即1843200个机器周期就是````````` //1S;考虑到单片机本身设计成倍频方式,所以实际上1S是3686400个机器周期。 */`*` DIG = 0xff; //关位码 TMOD = 0x01; //选用T0定时器,T0为定时方式,工作方式为1```` TH0 = 0x10; //中断初值 TL0 = 0x00; //中断初值 EA = 1; //开总中断 ET0 = 1; //允许T0中断 TR0 = 0; //关闭定时器T0 //**************超级循环************** while(1) { key(); //调用按键判断函数 display(); //调用扫描显示函数 } } /****************按键扫描*******************/ void key(void) { uchar q,w; //******k1按键扫描****** if(k1==0) //判断k1是否按下 { delay(5); //去抖 if(k1==0) //在判断k1是否真的按下 { TR0 = 1; //开启定时器0 keyk1=0; //k1按键按下时间清0 count++; //k1按下就加一 while(k1==0) //等待按键弹起 { display(); //调用扫描显示,让按键进入等待时数码管也显示 if(keyk1 >= 2) //k1按键按下超过1.5秒连续加一 { if(count!=99) //要显示的数超过99就不执行下列语句 { for(w=0;w<8;w++) //为了使加一的过程变的缓慢一些,以便看的清 { //如果有需要就改变for语句循环的次数 display( ); delay(2); display( ); delay(2); display( ); delay(2); display( ); delay(2); display( ); } count++; //上面for循环完毕后记数加一 } } } } } //*************k2按键扫描************ if(k2==0) { delay(5); if(k2==0) { TR0 = 1; keyk2 = 0; if(count) //记数值为0不执行减一功能 count--; while(k2==0) //等待按键弹起 { display(); //调用扫描显示,让按键进入等待时数码管也显示 if(keyk2 >= 2) { for(q=0;q<8;q++) { display( ); delay(2); display( ); delay(2); display( ); delay(2); display( ); delay(2); display( ); } if(count) //记数值为0是不执行减一功能 count--; } } //EA = 0;//关总中断 //ET0 = 0;//禁止T0中断 TR0 = 0;//关闭定时器T0 } } } /**************定时器T0中断程序****************/ void IntTimer0(void) interrupt 1 { TH0 = 0x10; TL0 = 0x00; IntCount++; //中断记数 if(IntCount == 45) //中断60次为1秒 { IntCount=0; keyk1++; //K1加一 keyk2++; //k2加一 } } /****************扫描显示******************/ void display(void) { uchar i; uchar scan = 0xfe; if(count >= 99) //超过99或者等于99的只显示99 count = 99; DispData[6] = count/10; DispData[7] = count%10; for(i=0;i<8;i++) //扫描显示8位 { SEG = SegTabl[DispData[i]]; //输出显示码 DIG = scan; //扫描位 delay(2); //延时 DIG = 0xff; //关显示 scan = (scan<<1)|0x01; //扫描下一位 } } /**************延时****************/ void delay(uint time) { uint i; uint j; for(i=0;i<time;i++) { for(j=0;j<130;j++); } }