这次我们用4个独立按键和8位数码管来做一个正计数器和倒计时器,到时间后(正计时最大值,倒计时最小值)LED灯闪烁10秒熄灭(大家可以先自己想好步骤,再看一下我下面的思路步骤)我用的单片机是STC89C52
主要的步骤:1、先思考正计数,倒计数需要定时器中断。还需要按键处理函数。另外需要一个数码管显示函数。
2、如何将这三个程序有序的排列组合起来形成一个完整的程序,这时我们可以从正计时器入手(也可以从倒计时入手)(由简入深,抓住主干)先规定K1代表正计数器的开和关,K2代表秒分时的移位,K3代表自加,K4代表自减。还有就是正计数到达最大值的时候LED灯进行闪烁。
3、这时就要用标志位来分清关系。
第一部分按键程序,具体操作就是用flag0代表正计数器的开关,knum代表K2按下的时候到底是秒分时哪个 ,K3代表按一下加,K4代表按一下减,这时我们的按键程序基本完成;
第二部分就是我们的定时器中断函数,因为定时器我选的时16位非自动重装10ms,所以要累计100次到一秒,大家要注意如果你选的是1ms定时,就需要累计1000次,记着你的数据类型要选int或者unsigned int,这部分容易忽略。还有当K2按下,标志位knum进行改变也就代表着秒分时要开始闪烁。这时要进行计数操作也就是当计数时间到时,flag1进行改变,控制秒分时的闪烁时间间隔。当计数时间到的时候还需要flag2的改变这样控制LED灯的闪烁频率以及时间。
第三部分就是我们的数码管显示程序,这个程序要根据knum的值进行改变,当knum=0时它直接进行显示,当knum!=0也就是K2按下的时候,根据flag1的值来闪烁。
第四部分就是我们要看到效果,当正计数器到达最大值的时候LED灯开始闪烁。只需在正计数结束的时候控制flag2。
第五部分当你把前四部分都解决了之后,那么你就可以着手做互锁关系了,当我们正计数的时候我们不能进行移位操作,也就是说正计数器的开启与移位操作形成互锁(我们可以加if语句这样就实现了)。
接下来就是K3,4长按和短按操作,短按加减一次,长按连加减。
我们想要实现的还有倒计时器的设定这时我们可以将K1也设定为长按和短按,长按倒计时器,短按正计数器。同时此时也会出现两者的相互干扰情况,于是再设定一个互锁,这样就就避免了(用if语句来解决,就用我们现成的标志位)。因为我们将K1,K3,K4都用了长按短按,所以就让K2的长按也有功能,就是全体清零,LED灯闪烁。
第六部分就是大家发现了吗?就是在进行长按的时候,由于我们这时候还想要数码管继续显示,所以我在长按的while循环里做了显示,但这个显示函数单次显示只用了1ms,这样我们显示了八次,再加上一次延时1ms,我近似认为一次长按循环所需时间为10ms,这一点大家做长按,短按的时候会遇到的,还有就是数码管显示函数的延时时间长短,会改变数码管亮度。大家可以自己写一下这个程序,写完就理解我为什么要这样写了。
有错误请指出,谢谢。
单片机源程序如下:
- #include"digdisplay.h"
- sbit k1=P3^1; //短按进行计数操作,长按进行倒计时操作
- sbit k2=P3^0; //短按进行秒分时的移位闪烁,长按进行秒分时归零,没有移位闪烁,LED灯闪烁开始
- sbit k3=P3^2; //短按进行秒分时(看K2让谁闪烁)的加一操作 ,长按进行连加操作(K2让谁闪烁)
- sbit k4=P3^3; //短按进行秒分时(看K2让谁闪烁)的减一操作 ,长按进行连减操作(K2让谁闪烁)
- sbit led=P2^0; //当计数到最大值时LED灯开始闪烁,当倒计时到零时开始闪烁
- u8 datenume[6]={0,0,0,0,0,0}; //当做存储秒分时的值,通过运算转换为数码管显示的值
- u8 miao=0,fen=0,shi=0,count,knum=0,flag0=0,time=0,flag1=0,flag2=0,flag3=0,time_count=0; //flag0是否进行计数操作,falg1秒分时的闪烁标志位,falg2是定时或计数到时LED灯进行闪烁,flag3是否进行倒计时操作,knum进行移位操作的标志性
- u8 a,b,c,d,e; //这几个都代表数值,计算时间用的,你可以在程序中发现它们
- void Delay5ms() //@12.000MHz
- {
- unsigned char i, j;
- i = 10;
- j = 183;
- do
- {
- while (--j);
- } while (--i);
- }
- void keyprogress() //对四个固定按键进行操作,具体操作如下
- {
- if(!k1)
- {
- Delay5ms();
- if(!k1)
- {
- while(!k1)
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- d++;
- Delay1ms();
- if(d==100)
- {
- if(knum==0&&flag0==0&&(miao!=0||fen!=0||shi!=0)) //计数器和倒计时形成互锁当秒分时都为零时不能进行倒计时
- {
- flag3=!flag3; //开启倒计时和关闭倒计时
- }
- }
- }
- if(d<100)
- {
- if(knum==0&&flag3==0) //当没进行移位操作时才可以启动计数器,解决了移位时计数器开启问题,互锁
- { //计数器和倒计时形成互锁
- flag0=!flag0; //开启计数器和关闭计数器
- }
- }
- d=0;
- }
- }
- if(!k2)
- {
- Delay5ms();
- if(!k2)
- {
- while(!k2)
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- e++;
- Delay1ms();
- if(e==100) //全体归零LED灯闪烁
- {
- flag0=0;
- flag1=0;
- flag2=1;
- flag3=0;
- knum=0;
- shi=0;
- fen=0;
- miao=0;
- }
- }
- if(flag0==0&&e<100) //解决了当移位操作时计数器开启问题,形成必须要计数器关闭才能开始移位,形成互锁
- {
- knum++;
- if(knum==4)
- {
- knum=0;
- }
- }
- e=0;
- }
- }
- if(!k3) //必须在有移位操作的时候才能加,也算一个锁定
- {
- Delay5ms();
- if(!k3)
- {
- while(!k3)
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- Delay1ms();
- a++;
- if(a==100)
- {
- a=50;
- if(knum==1)
- {
- miao++;
- if(miao==60)
- {
- miao=0;
- }
- }
- else if(knum==2)
- {
- fen++;
- if(fen==60)
- {
- fen=0;
- }
- }
- else if(knum==3)
- {
- shi++;
- if(shi==24)
- {
- shi=0;
- }
- }
- }
- }
- if(knum!=0)
- {
- if(a<50)
- {
- if(knum==1)
- {
- miao++;
- if(miao==60)
- {
- miao=0;
- }
- }
- else if(knum==2)
- {
- fen++;
- if(fen==60)
- {
- fen=0;
- }
- }
- else if(knum==3)
- {
- shi++;
- if(shi==24)
- {
- shi=0;
- }
- }
- }
- }
- a=0;
- }
- }
- if(!k4) //必须在有移位操作时才可以自减
- {
- Delay5ms();
- if(!k4)
- {
- while(!k4)
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- Delay1ms();
- a++;
- if(a==100)
- {
- a=50;
- if(knum==1)
- {
- miao--;
- if(miao==255)
- {
- miao=59;
- }
- }
- if(knum==2)
- {
- fen--;
- if(fen==255)
- {
- fen=59;
- }
- }
- if(knum==3)
- {
- shi--;
- if(shi==255)
- {
- shi=23;
- }
- }
- }
- }
- if(a<50)
- {
- if(knum==1)
- {
- miao--;
- if(miao==255)
- {
- miao=59;
- }
- }
- else if(knum==2)
- {
- fen--;
- if(fen==255)
- {
- fen=59;
- }
- }
- else if(knum==3)
- {
- shi--;
- if(shi==255)
- {
- shi=23;
- }
- }
- }
- a=0;
- }
- }
- }
- void shuma() //做数码管显示函数,当knum=0时普通显示,当knum!=0时靠标志位flag1决定闪烁
- {
- if(knum==0)
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- }
- else if(knum==1)
- {
- if(flag1)
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- }
- else
- {
- digdisplay(0,17);
- digdisplay(1,17);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- }
- }
- else if(knum==2)
- {
- if(flag1)
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- }
- else
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,17);
- digdisplay(4,17);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- }
- }
- else if(knum==3)
- {
- if(flag1)
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- }
- else
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,17);
- digdisplay(7,17);
- }
- }
- }
- void main()
- {
- TMOD &= 0xF0; //设置定时器模式
- TMOD |= 0x01; //设置定时器模式
- TL0 = 0xF0; //设置定时初值 10毫秒定时器
- TH0 = 0xD8; //设置定时初值
- TF0 = 0; //清除TF0标志
- TR0=1; //定时器开启 定时器在程序运行过程中将一直启动
- ET0=1;
- EA=1;
- while(1)
- {
- keyprogress(); //按键处理函数分别处理K1,K2,K3,K4的长按和短按程序
- shuma(); //数码管管显示程序,处理K2按键按下
- }
- }
- void int0() interrupt 1
- {
- TL0 = 0xF0; //设置定时初值
- TH0 = 0xD8; //设置定时初值
- datenume[0]=miao%10; //对秒分时进行数据处理,用数码管显示做铺垫
- datenume[1]=miao/10;
- datenume[2]=fen%10;
- datenume[3]=fen/10;
- datenume[4]=shi%10;
- datenume[5]=shi/10;
- if(flag0&&knum==0) //进行正向计数,knum判断是否进行了移位操作,flag0判断是否进行了开始操作
- {
- count++;
- if(count==100)
- {
- count=0;
- miao++;
- if(miao==60)
- {
- miao=0;
- fen++;
- if(fen==60)
- {
- fen=0;
- shi++;
- if(shi==24)
- {
- shi=0;
- flag2=!flag2; //开启LED灯的闪烁
- flag0=!flag0; //关闭计数器
- }
- }
- }
- }
- }
- if(flag3&&knum==0) //进行倒计时操作
- {
- time_count++;
- if(time_count==100)
- {
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
数码管与按键的组合使用.rar
(39.3 KB, 下载次数: 26)
|