1、./v .基于单片机的电子闹钟设计基于单片机的电子闹钟设计 摘要摘要 本设计以 AT89C51 芯片为核心,辅以必要的外围电路,设计了一个构造简单,功能齐全的电子时钟,它由 5V 直流电源供电。关键词:关键词:单片机;led;闹钟;定时器 A Abstractbstract This design,adopting AT89C51 chip as the core part with some necessary peripheral circuits,is a simple electronic clock which uses 5V DC as the power supply.Keywo
2、rds:Keywords:single chip machine,in fixed time machine,alarm clock,LED 1 1 引言引言 1.11.1 设计目的设计目的 此次课程设计是在学习先修课程?单片机原理与系统设计?之后,为加强对学生系统设计和应用能力的培养而开设的综合设计训练环节。本课程设计应结合?单片机原理与系统设计?课程的根底理论,重点强调实际应用技能训练,包括单片机系统设计的软件和硬件两局部。其课程设计任务是使学生通过应用单片机系统设计的根本理论,根本知识与根本技能,掌握单片机应用系统各主要环节的设计、调试方法,初步掌握并具备应用单片机进展设备技术改造和产品
3、开发的能力,培养学生的创新意识,提高学生的动手能力和分析问题、解决问题的能力。1.21.2 设计要求设计要求 结合单片机知识,以 AT89C51 单片机为核心,利用七段 LED 数码管实现计时、校时及闹钟功能。1.31.3 设计方法设计方法 以 AT89C51 单片机为核心,外加晶振电路,使用 8 个七段数码管显示,LED采用动态扫描,用 74ls245 芯片作为驱动电路。通过四个独立按键对时间进展定时、校时,从而实现闹钟提醒功能。2 2 设计方案及原理设计方案及原理 2.12.1 设计方案设计方案 选 AT89C51 单片机作为系统核心,辅助外部产生时钟信号的晶振电路,再加上四个独立按键作为
4、输入信号,使用 8 个七段数码管显示时间,芯片 74ls245 为数.-word.zl.码管段选线的驱动,最后用蜂鸣器实现闹铃功能。使用单片机的定时器 T0 计时时间为 50ms,计时 20 次作为 1s 的时间基准。第一局部,12MHz 的晶振连接至单片机的时钟信号输入端;第二局部,四个独立按键加上四个上拉电阻连接至单片机的 P1 口的低四位;第三局部,单片机的 P0 口通过由芯片 74ls245 构成的驱动电路连接至数码管的段选线,单片机的 P3 口连接至数码管的位选线;第四局部,单片机的 P2.1 通过一个 NPN 型三极管连接至蜂鸣器。8 个七段数码管使用动态扫描显示时间,独立按键用软
5、件编程实现对时间和闹钟时、分、秒的设臵,再通过比拟所设臵的闹钟与时间是否相等,到达闹铃发出声响的效果。2.22.2 设计原理设计原理 系统原理图如图 2.1 所示。图 2.1 系统原理图 3 3 硬件设计硬件设计 硬件电路分四个模块:晶振电路、键盘电路、数码管显示电路、蜂鸣器驱动电路。晶振电路使用 12MHz 晶体振荡器,经分频后供单片机工作。键盘采用 4 个独立按键配以 4 个上拉电阻实现对时钟和闹钟的设定及修改。由于通过数码管公共及的电流较大且防止过多地使用分立元件,采用了一片 74ls245 来驱动段码,用P3 口作位码驱动。发音局部是通过三极管放大驱动蜂鸣器工作,再通过软件这时产生等时
6、时间方波驱动蜂鸣器发出连续嘀声,这样就可以省去硬件振荡电路,降低本钱。系统硬件电路图如图 3.1 所示。AT89C51 晶振 按键 段码驱动 位码驱动 蜂鸣器 8 位数码管.-word.zl.图 3.1 系统硬件图 4 4 软件设计软件设计 源程序清单见附录。主程序流程图如图 4.1 所示。开始初始化设置闹铃判断显示时间键盘扫描 图 4.1 主程序流程图 5 5 系统仿真及调试系统仿真及调试 .-word.zl.硬件局部设臵了的三个按键 K1、K2、K3、K4。当按键 K1 第一次按下时,停顿计时进入闹钟 1 的秒设臵,当按键 K1 第二、第三次按下时,分别进入闹钟 1 的分设臵和时设臵,当按
7、 K1 第四、第五、第六次按下时分别进入闹钟 2 的秒、分、时设臵,当按 K1 第七、第八、第九次按下时分别进入闹钟 3 的秒、分、时设臵,当按 K1 第十、第二一、第十二次按下时分别进入时间的秒、分、时设臵,在 K1按下的各阶段,可用按键 K2、K3 进展时间和闹铃时间的时、分、秒进展加减设臵;当按键 K1 第十三次按下时恢复到时间显示功能。当显示的时间和定时设臵的时间一致时,蜂鸣器发出等时连续蜂鸣声,闹铃时间设臵为 60 秒。在各个闹钟设臵阶段,如果有 K4 按下,那么相应闹钟功能关闭或开启;如在闹铃时有 K4 按下那么提前停顿闹铃。系统仿真图如图 5.1 所示。图 5.1 系统仿真图 6
8、 6 总结总结 通过两周的努力,完成了电子闹钟的设计目的,实现了时间的显示、校时、设臵闹钟、闹铃等功能。这期间,我复习了单片机的相关知识,并结合查阅相关资料,设计了整体电路以及各模块的电路,对照硬件电路编写对应模块的子程序,.-word.zl.最后将各个子程序整合到一个主程序中,完成了设计所需功能。在设计中,我发现选择适宜的元器件很重要,比方数码管有共阳极和共阴极两种,不同的选择会导致程序的不同,经过屡次调试最终选择了共阳极数码管。另外,我觉得软件的设计比硬件设计更重要,而且难度更大。比方写一个程序看其功能很少认为编写程序简单,但到编程的时候才发现一些细微的知识或低级错误经常犯做不到最后常常失
9、败,所以有些东西只有学精弄懂并且要细心才行,只学习理论有些东西是很难理解的,更谈不上掌握。我在这次设计中收获颇多。我对所学的理论知识在实践中加深了认识,同时更加熟练掌握了 Proteus、Keil 等软件的使用。做任何事都需要耐心和细心,一点小的疏忽和懈怠可能导致整个设计失败。还有一点,自己的设计思路不可能凭空产生,只有借鉴别人已有的设计并充分消化吸收成为自己的东西,才能做出更好的设计作品。参考文献参考文献 1 王思明.单片机原理及应用系统设计M.:科学,2012.2 陈明荧.89C51 单片机课程设计实训教材M.:清华大学,2003.3 X 瑞新.单片机原理及应用教程M.:机械工业,2005
10、.4 杨文龙.单片机原理及应用M.:XX 电子科技大学,2002.附录附录 .-word.zl.源程序清单:源程序清单:/*头文件*#include#include/*宏定义*#define uchar unsigned char#define uint unsigned int/*位声明*sbit key1=P10;sbit key2=P11;sbit key3=P12;sbit key4=P13;sbit fmq=P21;/*数码管显示的数值*uchar code table=0 xc0,0 xf9,0 xa4,0 xb0,0 x99,0 x92,/0 1 2 3 4 5 0 x82,0
11、xf8,0 x80,0 x90,0 xbf,0 x0ff;/6 7 8 9 -灭 void jia();/定义时间加函数 void jian();/定义时间减函数/*数组定义,数组内含有 8 个数值*uchar table18,table28,table38,table48;/*时间显示初始值*uchar shi=12,fen=0,miao=0;/*定义全局变量*uchar shi1,fen1,miao1,shi2,fen2,miao2,shi3,fen3,miao3;uchar shi4,fen4,miao4;uchar flag,flag1,wss,t,t1,alm1,alm2,alm3;
12、/1 秒等时位闪次数校时闹 1 闹 2 闹 3 uint flag2;/蜂鸣/*延时函数,用于动态扫描数码管*void delay(uchar i)uchar x,y;for(x=i;x0;x-)for(y=120;y0;y-);/*初始化函数*.-word.zl.void init()TMOD=0 x01;/工作方式 1 TH0=0 x3c;/定时时间为:50ms(65536-50000)/256 TL0=0 x0b0;/(65536-50000)%256 ET0=1;/翻开定时器 EA=1;/开总中断 TR0=1;/启动定时器 /*显示子函数,用于显示时间数值*void display()
13、uchar i,j;if(t!=10|wss=0)table10=miao%10;/别离秒的个位与十位 table11=miao/10;else table10=table11=11;if(t!=11|wss=0)table13=fen%10;/别离分的个位与十位 table14=fen/10;else table13=table14=11;if(t!=12|wss=0)table16=shi%10;/别离时的个位与十位 table17=shi/10;else table16=table17=11;table12=table15=10;j=0 x7f;for(i=0;i=7;i+)/从秒到时的
14、扫描 P3=j;/选通点亮八个数码管 P0=tabletable1i;/显示数值 delay(10);/调用延时程序 j=_cror_(j,1);/循环右移 /*显示子函数,用于显示定时 1 时间*.-word.zl.void display1()uchar i,j;if(alm1=0)if(t!=1|wss=0)table20=miao1%10;/别离秒的个位与十位 table21=miao1/10;else table20=table21=11;if(t!=2|wss=0)table23=fen1%10;/别离分的个位与十位 table24=fen1/10;else table23=tab
15、le24=11;if(t!=3|wss=0)table26=shi1%10;/别离时的个位与十位 table27=shi1/10;else table26=table27=11;else table20=table21=table23=table24=table26=table27=10;table22=table25=10;j=0 x7f;for(i=0;i=7;i+)/从秒到时的扫描 P3=j;/选通点亮八个数码管 P0=tabletable2i;/显示数值 delay(10);/调用延时程序 j=_cror_(j,1);/循环右移 /*显示子函数,用于显示定时 2 时间*void dis
16、play2()uchar i,j;if(alm2=0)if(t!=4|wss=0)table30=miao2%10;/别离秒的个位与十位 table31=miao2/10;.-word.zl.else table30=table31=11;if(t!=5|wss=0)table33=fen2%10;/别离分的个位与十位 table34=fen2/10;else table33=table34=11;if(t!=6|wss=0)table36=shi2%10;/别离时的个位与十位 table37=shi2/10;else table36=table37=11;else table30=table
17、31=table33=table34=table36=table37=10;table32=table35=10;j=0 x7f;for(i=0;i=7;i+)/从秒到时的扫描 P3=j;/选通点亮八个数码管 P0=tabletable3i;/显示数值 delay(10);/调用延时程序 j=_cror_(j,1);/循环右移 /*显示子函数,用于显示定时 3 时间数值*/void display3()uchar i,j;if(alm3=0)if(t!=7|wss=0)table40=miao3%10;/别离秒的个位与十位 table41=miao3/10;else table40=table
18、41=11;if(t!=8|wss=0)table43=fen3%10;/别离分的个位与十位 table44=fen3/10;.-word.zl.else table43=table44=11;if(t!=9|wss=0)table46=shi3%10;/别离时的个位与十位 table47=shi3/10;else table46=table47=11;else table40=table41=table43=table44=table46=table47=10;table42=table45=10;j=0 x7f;for(i=0;i=20)/判断是否到一秒 wss=wss;flag=0;/到
19、了,那么标志位清零 if(t1!=0)miao4+;/秒加 1 if(miao459)/判断秒是否到 60s miao4=0;/到了,那么清零 fen4+;/分加 1 if(fen459)/判断分是否到 1min fen4=0;/到了,那么清零 shi4+;/时加 1 if(shi423)/判断时是否到 24h shi4=0;/到了,那么清零 else.-word.zl.miao+;/秒加 1 if(miao59)/判断秒是否到 60s miao=0;/到了,那么清零 fen+;/分加 1 if(fen59)/判断分是否到 1min fen=0;/到了,那么清零 shi+;/时加 1 if(s
20、hi23)/判断时是否到 24h shi=0;/到了,那么清零 /*键盘扫描子函数*/void key_scan()if(key1=0)while(!key1)/防止掉显 if(t=1|t=2|t=3)display1();/key1 按了 1、2、3 次,调用闹钟 1 子程序 if(t=4|t=5|t=6)display2();/key1 按了 4、5、6 次,调用闹钟 2 子程序 if(t=7|t=8|t=9)display3();/key1 按了 7、8、9 次,调用闹钟 3 子程序 if(t=0|t=10|t=11|t=12|t=13)display();/key1 按了 10、11、
21、12、13 次,调用计时子程序 t+;/记下按键 key1 按下的次数 if(t=10&t1=0)miao4=miao;fen4=fen;shi4=shi;t1+;if(t=13)t=0;if(t1=1)miao=miao4;fen=fen4;shi=shi4;.-word.zl.t1=0;if(key2=0)/判断 key2 是否按下 while(!key2)/防止掉显 if(t=1|t=2|t=3)display1();if(t=4|t=5|t=6)display2();if(t=7|t=8|t=9)display3();if(t=0|t=10|t=11|t=12|t=13)display
22、();jia();/调用加 1 子函数 if(key3=0)/判断 key3 是否按下 while(!key3)/防止掉显 if(t=1|t=2|t=3)display1();if(t=4|t=5|t=6)display2();if(t=7|t=8|t=9)display3();if(t=0|t=10|t=11|t=12|t=13)display();jian();/调用减 1 子函数 if(key4=0)/判断 key4 是否按下 while(!key4)/防止掉显 if(t=1|t=2|t=3)alm1=alm1;display1();if(t=4|t=5|t=6)alm2=alm2;di
23、splay2();.-word.zl.if(t=7|t=8|t=9)alm3=alm3;display3();if(t=0|t=10|t=11|t=12|t=13)display();/*加 1 子函数*void jia()if(t=1)/判断 key1 按下的次数是否为 1 miao1+;/是,那么秒加 1 if(miao159)/判断秒是否大于 60,是,那么秒清零 miao1=0;if(t=2)/判断 key1 按下的次数是否为 2 fen1+;/是,那么分加 1 if(fen159)/判断分是否大于 60 fen1=0;/是,那么分清零 if(t=3)/判断 key1 按下的次数是否为
24、 3 shi1+;/是,那么时加 1 if(shi123)/判断时是否大于 23 shi1=0;/是,那么时清零 if(t=4)/判断 key1 按下的次数是否为 4 miao2+;/是,那么秒加 1 if(miao259)/判断秒是否大于 60,是,那么秒清零 miao2=0;if(t=5)/判断 key1 按下的次数是否为 5 fen2+;/是,那么分加 1 if(fen259)/判断分是否大于 60 fen2=0;/是,那么分清零 if(t=6)/判断 key1 按下的次数是否为 6 shi2+;/是,那么时加 1 if(shi223)/判断时是否大于 23 shi2=0;/是,那么时清
25、零.-word.zl.if(t=7)/判断 key1 按下的次数是否为 7 miao3+;/是,那么秒加 1 if(miao359)/判断秒是否大于 60,是,那么秒清零 miao3=0;if(t=8)/判断 key1 按下的次数是否为 8 fen3+;/是,那么分加 1 if(fen359)/判断分是否大于 60 fen3=0;/是,那么分清零 if(t=9)/判断 key1 按下的次数是否为 9 shi3+;/是,那么时加 1 if(shi323)/判断时是否大于 23 shi3=0;/是,那么时清零 if(t=10)/判断 key1 按下的次数是否为 10 miao+;/是,那么秒加 1
26、 if(miao59)/判断秒是否大于 60,是,那么秒清零 miao=0;t1+;if(t=11)/判断 key1 按下的次数是否为 11 fen+;/是,那么分加 1 if(fen59)/判断分是否大于 60 fen=0;/是,那么分清零 t1+;if(t=12)/判断 key1 按下的次数是否为 12 shi+;/是,那么时加 1 if(shi23)/判断时是否大于 23 shi=0;/是,那么时清零 t1+;/*减 1 子函数*/void jian()if(t=1)/判断 key1 按下的次数是否为 1,是那么秒减 1 miao1-;if(miao1=255)/判断秒是否减到 255,
27、是,那么秒臵 59.-word.zl.miao1=59;if(t=2)/判断 key1 按下的次数是否为 2,是那么分减 1 fen1-;if(fen1=255)/判断分是否减到 255,是,那么分臵 59 fen1=59;if(t=3)/判断 key1 按下的次数是否为 3,是那么时减 1 shi1-;if(shi1=255)/判断时是否减到 255,是,那么时臵 23 shi1=23;if(t=4)/判断 key1 按下的次数是否为 4,是那么秒减 1 miao2-;if(miao2=255)/判断秒是否减到 255,是,那么秒臵 59 miao2=59;if(t=5)/判断 key1 按
28、下的次数是否为 5,是那么分减 1 fen2-;if(fen2=255)/判断分是否减到 255,是,那么分臵 59 fen2=59;if(t=6)/判断 key1 按下的次数是否为 6,是那么时减 1 shi2-;if(shi2=255)/判断时是否减到 255,是,那么时臵 23 shi2=23;if(t=7)/判断 key1 按下的次数是否为 7,是那么秒减 1 miao3-;if(miao3=255)/判断秒是否减到 255,是,那么秒臵 59 miao3=59;if(t=8)/判断 key1 按下的次数是否为 8,是那么分减 1 fen3-;if(fen3=255)/判断分是否减到
29、255,是,那么分臵 59 fen3=59;if(t=9)/判断 key1 按下的次数是否为 9,是那么时减 1 shi3-;if(shi3=255)/判断时是否减到 255,是,那么时臵 23.-word.zl.shi3=23;if(t=10)/判断 key1 按下的次数是否为 10,是那么秒减 1 miao-;if(miao=255)/判断秒是否减到 255,是,那么秒臵 59 miao=59;t1+;if(t=11)/判断 key1 按下的次数是否为 11,是那么分减 1 fen-;if(fen=255)/判断分是否减到 255,是,那么分臵 59 fen=59;t1+;if(t=12)
30、/判断 key1 按下的次数是否为 12,是那么时减 1 shi-;if(shi=255)/判断时是否减到 255,是,那么时臵 23 shi=23;t1+;/*闹铃子函数*/void clock()/判断秒的数值是否相等 if(miao=miao1&alm1=0|miao=miao2&alm2=0|miao=miao3&alm3=0)/是,在判断分是否相等 if(fen=fen1&alm1=0|fen=fen2&alm2=0|fen=fen3&alm3=0)/是,再判断时是否相等 if(shi=shi1&alm1=0|shi=shi2&alm2=0|shi=shi3&alm3=0)flag2
31、=0;/是,那么标志位,flag2 清零 while(!(flag2=1200)&(t=0)/判断 flag2 是否到 1200 且不 /为调时状态 if(key4=0)/没有,那么继续驱动蜂鸣器响 while(!key4)flag2=1200;if(flag11)/等时方波驱动蜂鸣器 fmq=fmq;flag1=0;.-word.zl.shijian();/调用时间子函数 display();/调用显示子函数 fmq=1;/关闭蜂鸣器 /*主函数*/void main()init();/调用初始化子函数 while(1)clock();/闹钟子函数 if(t=1|t=2|t=3)/显示子函数 display1();if(t=4|t=5|t=6)display2();if(t=7|t=8|t=9)display3();if(t=0|t=10|t=11|t=12|t=13)display();shijian();/调用时间子函数 key_scan();/调用键盘扫描子函数 /*定时中断*/void time0()interrupt 1 TH0=0 x3c;/初值 50ms(65536-50000)/256 TL0=0 x0b0;/(65536-50000)%256 flag+;/标志位 flag1+;flag2+;