在之前的文章中我们学习了数码管定时闹钟中的按键中断的写法,接下来我们需要将我们的按键、蜂鸣器和我们之前设计的数码管计时器相结合起来,就可以实现一个数字时间现实的定时闹钟了。
一、功能概述
通过按键来控制设定的时间,当到达时间后进入外部中断,蜂鸣器开始工作,实现定时闹钟的功能。时间数字在四位数码管上进行显示,分钟倒计时定时闹钟的功能,在此基础上还可以添加小时的数码管,来对小时的时间进行设置,原理还是类似的。
(相关资料图)
二、显示原
本设计同样采用的AT89C51单片机来实现多位数码管的控制,附带按键设置时间,以及蜂鸣器闹钟的功能。
电路连接如下:
三、程序代码设计
结合我们前几章所学的数码管以及定时器、中断的方法来对程序进行编写。
程序如下:
#include< reg52.h >#include< intrins.h >#define uchar unsigned char#define uint unsigned intsbit key1=P3^0;//按键sbit key2=P3^1;sbit key3=P3^2;sbit key4=P3^3;sbit buffer=P2^3;//蜂鸣器sbit DU =P2^6;//段选sbit WE =P2^7;//位选uchar bitdata[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//数码管1-8uchar segdata[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//段选0-9,-uchar dis_arr[]={10,10,10,10,10,10};//时钟显示数组uchar time[]={0,0,0};//时钟 时分秒uchar time_In[]={0,0,0,0,0,0};uchar time_clk[]={0,0,0};//闹钟 时分秒uchar num=0;uchar mode=0;uchar keydown=0;uchar clk_state=0;uchar keyIn,keyvalue,i,temp;//矩阵键盘读入void key();void init();uchar keyscan();//矩阵键盘扫描函数void delayms(uint x);//延时函数void display(uchar duan1,uchar duan2,uchar duan3,uchar duan4,uchar duan5,uchar duan6);void display_1(uchar wei,uchar duan);void input();void soundTime();void main(){input();init();while(1){key();if(mode==0)//时钟 display(time[0]/10,time[0]%10,time[1]/10,time[1]%10,time[2]/10,time[2]%10);else if(mode==1)//闹钟display(time_clk[0]/10,time_clk[0]%10,time_clk[1]/10,time_clk[1]%10,time_clk[2]/10,time_clk[2]%10);}}void init()//初始化函数{P3=0xff;//给高电平TMOD=0x01;//定时器工作方式选择1TH0=(65536-45872)/256;TL0=(65536-45872)%256;EA=1; //开总中断ET0=1;//允许定时器0中断TR0=1;//开始计数//P1=1;}void delayms(uint x)//延时函数{uint i,j;for(i=x;i >0;i--)for(j=110;j >0;j--);}void key(){while(key2==0){input();break;}if(key1==0){delayms(200);if(key1==0)//{while(!key1){TR0=0;display(time[0]/10,time[0]%10,time[1]/10,time[1]%10,time[2]/10,time[2]%10);}TR0=1;}{TR0=!TR0;while(!key1)display(time[0]/10,time[0]%10,time[1]/10,time[1]%10,time[2]/10,time[2]%10);}//else if(TR0==0)TR0=1;}else if(key1==1){mode++;if(mode==2)mode=0;}}if(key3==0){delayms(200);if(key3==0){if(mode==0){time[0]=0;time[1]=0;time[2]=0;num=0;while(!key3)display(time[0]/10,time[0]%10,time[1]/10,time[1]%10,time[2]/10,time[2]%10);}else if(mode==1){time_clk[0]=0;time_clk[1]=0;time_clk[2]=0;while(!key3)display(time_clk[0]/10,time_clk[0]%10,time_clk[1]/10,time_clk[1]%10,time_clk[2]/10,time_clk[2]%10);}}else if(key3==1){buffer=1;/*P1=1;*/}}}uchar keyscan()//矩阵键盘扫描函数{keyvalue=99;P3=0xfe;temp=P3; temp=temp&0xf0;//判断是否还等于0xf0while(temp!=0xf0){delayms(5);temp=P3;temp=temp&0xf0;while(temp!=0xf0){temp=P3;switch(temp){case 0xee:{keyvalue=0;keydown=1;break;}case 0xde:{keyvalue=1;keydown=1;break;}case 0xbe:{keyvalue=2;keydown=1;break;}case 0x7e:{keyvalue=3;keydown=1;break;}}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}P3=0xfd;temp=P3; temp=temp&0xf0;//判断是否还等于0xf0while(temp!=0xf0){delayms(5);temp=P3;temp=temp&0xf0;while(temp!=0xf0){temp=P3;switch(temp){case 0xed:{keyvalue=4;keydown=1;break;}case 0xdd:{keyvalue=5;keydown=1;break;}case 0xbd:{keyvalue=6;keydown=1;break;}case 0x7d:{keyvalue=7;keydown=1;break;}}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}P3=0xfb;temp=P3; temp=temp&0xf0;//判断是否还等于0xf0while(temp!=0xf0){delayms(5);temp=P3;temp=temp&0xf0;while(temp!=0xf0){temp=P3;switch(temp){case 0xeb:{keyvalue=8;keydown=1;break;}case 0xdb:{keyvalue=9;keydown=1;break;}case 0xbb:{keyvalue=10;keydown=1;break;}case 0x7b:{keyvalue=11;keydown=1;break;}}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}P3=0xf7;temp=P3; temp=temp&0xf0;//判断是否还等于0xf0while(temp!=0xf0){delayms(5);temp=P3;temp=temp&0xf0;while(temp!=0xf0){temp=P3;switch(temp){case 0xe7:{keyvalue=12;keydown=1;break;}case 0xd7:{keyvalue=13;keydown=1;break;}case 0xb7:{keyvalue=14;keydown=1;break;}case 0x77:{keyvalue=15;keydown=1;break;}}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}return keyvalue;}void display(uchar duan1,uchar duan2,uchar duan3,uchar duan4,uchar duan5,uchar duan6){display_1(0,duan1);delayms(1);display_1(1,duan2);delayms(1);display_1(2,10);delayms(1);display_1(3,duan3);delayms(1);display_1(4,duan4);delayms(1);display_1(5,10);delayms(1);display_1(6,duan5);delayms(1);display_1(7,duan6);delayms(1);}void display_1(uchar wei,uchar duan){DU=1;P0=segdata[duan];DU=0;P0=0xff;WE=1;P0=bitdata[wei];WE=0;P0=0x00;}void input()//输入{EA=0;for(i=0;i< 8;i++)//重置为-便于下次使用dis_arr[i]=10;while(1){display(dis_arr[0],dis_arr[1],dis_arr[2],dis_arr[3],dis_arr[4],dis_arr[5]);keyIn=keyscan();if(keydown==1){keydown=0;dis_arr[0]=keyIn;time_In[0]=keyIn;if(time_In[0] >=0&&time_In[0]<=2)break;}}while(1){display(dis_arr[0],dis_arr[1],dis_arr[2],dis_arr[3],dis_arr[4],dis_arr[5]);keyIn=keyscan();if(keydown==1){keydown=0;dis_arr[1]=keyIn;time_In[1]=keyIn;if((time_In[1] >=0&&time_In[1]<=9)&&(time_In[0]*10+time_In[1])< 24)break;}}while(1){display(dis_arr[0],dis_arr[1],dis_arr[2],dis_arr[3],dis_arr[4],dis_arr[5]);keyIn=keyscan();if(keydown==1){keydown=0;dis_arr[2]=keyIn;time_In[2]=keyIn;if(time_In[2] >=0&&time_In[2]<=5)break;}}while(1){display(dis_arr[0],dis_arr[1],dis_arr[2],dis_arr[3],dis_arr[4],dis_arr[5]);keyIn=keyscan();if(keydown==1){keydown=0;dis_arr[3]=keyIn;time_In[3]=keyIn;if((time_In[3] >=0&&time_In[3]<=9)&&(time_In[2]*10+time_In[3])< 60)break;}}while(1){display(dis_arr[0],dis_arr[1],dis_arr[2],dis_arr[3],dis_arr[4],dis_arr[5]);keyIn=keyscan();if(keydown==1){keydown=0;dis_arr[4]=keyIn;time_In[4]=keyIn;if(time_In[4] >=0&&time_In[4]<=5)break;}}while(1){display(dis_arr[0],dis_arr[1],dis_arr[2],dis_arr[3],dis_arr[4],dis_arr[5]);keyIn=keyscan();if(keydown==1){keydown=0;dis_arr[5]=keyIn;time_In[5]=keyIn;if((time_In[5] >=0&&time_In[5]<=9)&&(time_In[4]*10+time_In[5])< 60){if(mode==0){time[0]=time_In[0]*10+time_In[1];time[1]=time_In[2]*10+time_In[3];time[2]=time_In[4]*10+time_In[5];}else if(mode==1){time_clk[0]=time_In[0]*10+time_In[1];time_clk[1]=time_In[2]*10+time_In[3];time_clk[2]=time_In[4]*10+time_In[5];}break;}}}while(1){display(dis_arr[0],dis_arr[1],dis_arr[2],dis_arr[3],dis_arr[4],dis_arr[5]);if(key3==0){delayms(10);if(key3==0){EA=1;break;}}}}void T0_time() interrupt 1//中断函数{TH0=(65536-45872)/256;TL0=(65536-45872)%256;num++;if(num==20)//循环20次为一秒{num=0;time[2]++;//秒加一if(time[2]==60)//秒到60进位{time[2]=0;//秒清零分钟加一time[1]++;if(time[1]==60)//分钟到60进位{time[1]=0;//分钟清零小时加一time[0]++; soundTime();//整点报时if(time[0]==24)//小时满24清零time[0]=0;}}if((time[0]==time_clk[0])&&(time[1]==time_clk[1])&&(time[2]==time_clk[2])){buffer=0;/*P1=0;*/}}}void soundTime(){buffer=0;delayms(10);buffer=1;}
四、总结
到这一章我们所学习的数码管应用也结束了,其实并没有想象中的复杂,数码管从一位到多位,段码并没有变化,而是用不同的位码来对每一个数码管进行控制,在之后我们还可以使用定时器的功能来实现对时间的计算,后来增加了外部中断,这使得时间可以由我们个人去通过按键来设定,在增加蜂鸣器就实现了数码管定时闹钟的设计目标。接下来我们将对SHT30温湿度传感器进行设计。