1、 毕业教学环节成果 2014年 05月23日 理工类 XXXXXXX学院毕业教学成果 目 录 摘要 1 英文摘要 2 引言 3 1 系统方案的设计 5 1.1 功能要求 5 1.2 方案设计思路 5 2 系统硬件电路设计 6 2.1 单片机最小系统的设计 6 2.2 时钟显示模块的设计 7 2.3 按键模块 8 2.4 液晶显示模块 9 2.5 蜂鸣器报警模块模块 10 3 软件设计 12 3.1 软件设计总体方案
2、12 3.1.1 主程序流程图 123.2 按键模块实现 13 4 系统软件仿真及结果分析 14 4.1 Proteus软件简介 14 4.2 Proteus软件仿真过程 144.3 仿真结果 15 结论与谢辞 17 参考文献 18附件1电路原理图 19 附件2电路PCB图 19 附件3程序源代码 20 附件4元器件清单 46 多功能数字钟电路的设计信息工程学院 应用电子技术 关键词: 电子时钟 单片机 DS1302 LCD1602 XX Abstract:Digital clock has become the indispensab
3、le necessities in People's Daily life, it is widely applied to people's life, study, work and entertainment extremely convenient. This design USES AT89C51 as the nucleus is the main control chip, for DS1302 clock chip, LCD1602 LCD display time, through the key module to set the date and alarm Settin
4、gs. Software part mainly accomplished by programming of c program for time clock chip data read and write, and then through the liquid crystal display program can display the time conversion functions are implemented by keystrokes and switch of the screen. This design can be implemented according to
5、 the basic functions of time, during school hour alarm function. Keywords: electronic clock single chip DS1302 LCD1602 时间是人类生活必不可少的重要元素,如果没有时间的概念,社会将不会有所发展和进步。从古代的水漏、十二天干地支,到后来的机械钟表以及当今的石英钟,都充分显现出了时间的重要,同时也代表着科技的进步。致力于计时器的研究和充分发挥时钟的作用,将有着重要的意义。 电子钟是采用电子电路实现对时、分、秒进行数字显示的计时装置,广泛应用于个人家庭,车站, 码头办公室等
6、公共场所,成为人们日常生活中不可少的必需品。由于数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字钟的精度,远远超过老式钟表,钟表的数字化给人们生产生活带来了极大的方便,而且大大地扩展了钟表原先的报时功能。诸如定时自动报警、0按时自动打铃、定时广播、自动起闭路灯、定时开关烘箱、通断动力设备、甚至各种定时电气的自动启用等,所有这些,都是以钟表数字化为基础的。因此,研究数字钟及扩大其应用,有着非常现实的意义。 电子时钟主要是利用电子技术将时钟电子化、数字化,拥有时间精确、体积小、界面友好、可扩展性能强等特点,被广泛应用于生活和工作当中。当今市场上的电子时钟品类繁多,外形小巧别致。也有体型较大
7、的,诸如公共场所的大型电子报时器等。电子时钟首先是数字化了的时间显示或报时器,在此基础上,人们可以根据不同场合的要求,在时钟上加置其他功能,比如定时闹铃,万年历,环境温度、湿度检测,环境空气质量检测,USB扩展口功能等。 1 系统方案的设计 (1) 以数字形式显示时、分、秒的时间。 (2)手动快校时、快校分或慢校时、慢校分。 (3)定时控制、仿广播电台整点报时等功能。 本次设计主要以数字形式显示年月日和手动快校时,快校分或慢校时,慢校分,实现整点报时和闹铃的功能。 在硬件电路设计方面主要包括单片机最小系统,DS1302时钟芯片电路模块,LCD1602液晶显示模块,按键模块
8、以及蜂鸣器报警模块。 在软件方面主要是采用c语言来进行编程,实现对时钟芯片进行时间数据的读和写,然后通过液晶显示程序将时间显示出来,通过按键操作实现功能的转换和屏幕的切换。设计中结合硬件、软件的分步调试,达到要求的控制效果。 2 系统硬件电路设计2.1 单片机最小系统的设计 AT89C51是一款非常适合单片机初学者学习的单片机,它是美国Atmel公司生产的低功耗、高性能CMOS8位单片机,片内含4KB可系统编程的Flash只读程序存储器,器件采用Atmel公司的高密度、非易失性存储技术生产,兼容标准8051指令系统及
9、引脚。它集Flash程序存储器,即可在线编程(ISP),也可以用传统方法进行编程可灵活应用于各种控制领域。 AT89C51单片机最小系统如图1所示。 图1 单片机最小系统 单片机AT89C51的主要技术参数如表1所示。 主要功能特性 4K字节可编程闪烁存储器 寿命:1000写/擦循环 数据保留时间:10年 全静态工作:0Hz-24Hz 三级程序存储器锁定 128*8位内部RAM 两个16位定时器/计数器 可编程串行通道 低功耗的闲置和掉电模式 片内振荡器和时钟电路 5
10、个中断源 与MCS-51 兼容 ~5.5V 图4按键电路 按键模块功能描述如下: 1)该电子钟有四个按键S0、S1、S2、S3、S4分别是闹钟停止键、时间设置和闹钟设置键,加一键、减一键、移动键。具体按键说明如下: 2)S0闹钟停止键:当闹钟响起的时候,按下此键,可以关闭闹钟。 3)S1时间校准键、闹钟设置键:按下这个键后LCD液晶屏进入按下此键进入预置时间状态,依次按两下进入闹钟设置状态。在以上两种状态下可进行小时、分、秒设定,设定完成后在按下此键退出预置时间状态或闹钟设置状态,进入正常走时状态。 4)S2加1键:在调整年、月、日、星期、小时、分
11、秒时间数值时按下此键时相应的数值加一。 5)S3减1键:与S2相反。 6)S4移动键:当时钟进入到预置时间状态或闹钟设置状态时,依次按下此键进行年、月日、星期、小时、分、秒的位子移动变化,进行时间的设定,设定完成后,按下S1键退出状态,进入正常走时状态。 2.4 液晶显示模块 LCD1602主要技术参数 编号 符号 引脚说明 编号 符号 引脚说明 1 VSS 电源地 9 D2 数据 2 VDD 电源正极 10 D3 数据 3 VL 液晶显示偏压 11 D4 数据 4 RS 数据/命令选择 12 D
12、5 数据 5 R/W 读/写选择 13 D6 数据 6 E 使能信号 14 D7 数据 7 D0 数据 15 BLA 背光源正极 8 D1 数据 16 BLK 背光源负极 2.5 蜂鸣器报警模块 蜂鸣器报警模块的作用:当定时闹钟时间到时,蜂鸣器发出预设的声音,而发光二极管则会随着音乐闪烁。本模块采用PNP三极管为蜂鸣器放大电流,基极通过1k电阻与单片机AT89C51的闲置引脚P3.4相连接,集电极直接接地,发射极接发光二极管和蜂鸣器。 图8 报警电路 本系统的程序采用C语言编写,为了便于修改和调试,系统软件采用模块化设计,程序的编
13、写编译在WAVE6000软件中完成。 3.1.1 主程序流程图 主程序流程图如图9所示。 初始化设置 闹钟判断 整点判断 显示 按键扫描 开始 图9 主程序流程图 首先对AT89C51、DS1302、LCD1602进行初始化,时间通过LCD1602显示出来,同时进行按键扫描,判断哪个键按下,如果时间与设定的闹钟时间相同后,单片机通过报警模块进行警报,此时,若按下S0按键,报警停止,LCD1602显示的时间继续精确显示。主程序代码见附件3。 3.2 按键模块软件的实现 按键模块流程图如图10所示。 图10按键子程序流
14、程图 在按键扫描状态的时候,先判断是否有键按下,如果有键按下,读取相应的键值,进入到相应键值的功能状态。如图11所示,按键模块子程序详见附录3。 4 PROTEUS软件 4.1 Proteus软件 我们软件调试一般使用Proteus ISIS 7和Keil整合进行仿真调试。其中Keil作为软件调试界面,Proteus作为硬件仿真和调试界面,下面说一下如何操作: (1)用Keil软件写出相应的51程序,并进行编译,直到编译成功。 (2)打开Proteus软件。 (3)选择file菜单下的 open design选项,找到所需的元器件,元器件上单击右键选中,再单击左键对其进行命名
15、和赋值,接着在编辑器左边的一栏中,找出并绘制设计所要的各种元器件,按照电路图连接后并保存。 (4)将用keil编译产生的hex文件下载到单片机中:双击单片机,在对话框中把保存过的hex文件打开,再单击确定。 (5)单击左下角运行按钮,进行软件仿真调试,直到出现正确的结果。 本次设计仿真流程图如图11所示,效果图如图12所示。 绘制原理图 程序编写和编译 装载HEX代码调试 得到仿真效果 图11仿真流程图 图12仿真效果图 4.2 仿真结果 如图13所示,当电子钟整点时,发光二极管亮,蜂鸣器响。 图13 整点报时 电子钟
16、时间设置仿真如图14图15所示,当电子钟运行时,光标闪烁,电子钟进入时间设置状态或闹钟设置状态。 图14 时间设置状态仿真 图15闹钟设置状态仿真 经过调试,结果满足设计要求,验证无误。通过单片机硬件电路的调试,实现了预先设定的功能,设计主要用到的元件不多,最主要的是程序也比较长比较麻烦,同时也遇到了少量困难,尤其是关于校时模块的设计实现。关于显示模块,在以前的实验中做过,所以问题很容易解决。学以致用,将从书本上学到的知识应用于实践,学会初步的电子电路仿真设计。 本次课程设计是用AT89C51单片机CPU及LCD1602设计一个数字时钟,虽然过程中遇到了一些困难
17、但是在解决这些问题的过程无疑也是对自己自身专业素质的一种提高。当最终调试成功的时候也是对自己的一种肯定。此次的设计作业不仅增强了自己在专业设计方面的信心,鼓舞了自己,更是一次兴趣的培养,为自己以后的学习方向的明确了重点。 另外在这次实验中我们遇到了不少的问题针对不同的问题我们采取不同的解决方法,最终一一解决设计中遇到的问题。在我们曾经遇到不懂的问题时,利用网上的资源,搜索查找得到需要的信息。 总的来说,这次设计的多功能数字电子钟的电路设计还是比较成功的,在设计中遇到了很多问题,最后在老师的辛勤的指导下,终于迎刃而解,有点小小的成就感,终于觉得平时所学的知识有了实用的价值,达到了理论与实际
18、相结合的目的,不仅学到了不少知识,而且锻炼了自己的能力,使自己对以后的路有了更加清楚的认识,同时,对未来有了更多的信心。在本文的撰写过程中,XXX老师作为我的指导老师,她教学严谨,为我营造了一种良好的学术氛围。在此特向XXX老师致以衷心的谢意!
参考文献
附件1电路原理图
附件2电路PCB图
附件1程序源代码
#include
19、d init_Led1602(void); void init_DS1302(void); void Normal( ); void key4(); void key5(); /***********************延时程序*********************************/ void delay(uint z) { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void main() { init_DS1302(); //初始化1302 i
20、nit_Led1602(); //初始化Led1602 while(1) { disp(); //显示 } } /********************************ds1302***************************************/ //***************向DS1302写入一字节数据 void Write1302(uchar addr, uchar d) { unsigned char i; SCK=0; RST=1; //写入目标地址:addr
21、 for (i = 0; i < 8; i ++) { if (addr & 0x01) { SDA=1; } else { SDA=0; } //并口转串口 SCK=1; //上升沿写数据 SCK=0; addr = addr >> 1; } //写入
22、数据:d for (i = 0; i < 8; i ++) { if (d & 0x01) { SDA=1; } else { SDA=0; } SCK=1; SCK=0; d = d >> 1; } RST=0; //停止DS1302总线 } //*************************从DS1
23、302读出一字节数据 unsigned char Read1302(uchar addr) { unsigned char i; unsigned char temp; unsigned char dat1=0; unsigned char dat2=0; SCK=0; RST=1; //写入目标地址:addr for (i = 0; i < 8; i ++) { if (addr & 0x01) { SDA=1; } else
24、 { SDA=0; } SCK=1; SCK=0; addr = addr >> 1; } //输出数据:temp for (i = 0; i < 8; i ++) { temp = temp >> 1; if (SDA) { temp |= 0x80; } else { temp &= 0x7F;
25、} SCK=1; SCK=0; } RST=0; //停止DS1302总线 dat2 = temp/16; // 数据进制转换 dat1 = temp%16; dat1 = dat2*10+dat1; return dat1; } /*****************************1602显示******************************************/ void write_add(uchar add)
26、 //1602控制字 { RS=0; P0=add; EN=1; delay(5); EN=0; } void write_date(uchar date) //1602显示字 { RS=1; P0=date; EN=1; delay(5); EN=0; } void writesfm(uchar add,uchar date) //1602显示时分秒 { uchar s,g; s = date/10; g = date%10;
27、 write_add(0x80+0x40+add); write_date(0x30+s); write_date(0x30+g); } void writenyr(uchar add,uchar date) //1602显示年月日 { uchar s,g; s=date/10; g=date%10; write_add(0x80+0x00+add); write_date(0x30+s); write_date(0x30+g); } void writexi(uchar a) { write_
28、add(0x80+0x00+11); if(a==1) { for(i=0;i<3;i++) { write_date(xi1[i]); delay(5); } } if(a==2) { for(i=0;i<3;i++) { write_date(xi2[i]); delay(5); } } if(a==3) { for(i=0;i<3;i++) { write_dat
29、e(xi3[i]); delay(5); } } if(a==4) { for(i=0;i<3;i++) { write_date(xi4[i]); delay(5); } } if(a==5) { for(i=0;i<3;i++) { write_date(xi5[i]); delay(5); } } if(a==6) { for(i=0;i<3;i++) { wr
30、ite_date(xi6[i]); delay(5); } } if(a==7) { for(i=0;i<3;i++) { write_date(xi7[i]); delay(5); } } } void writefuhao(void) //写符号 { write_add(0x80+0x00+2); write_date(table[2]); delay(10); write_add(0x80+0x00+5); write_date(tabl
31、e[2]); delay(10); write_add(0x80+0x40+2); write_date(time1[2]); delay(10); write_add(0x80+0x40+5); write_date(time1[2]); delay(10); } void Speak1() //闹铃 { alarm = 0; smiao = Read1302(r_Sec); sfen = Read1302(r_Min); sshi = Read1302(r_Hou); snian = Read13
32、02(r_Yea); syue = Read1302(r_Mou); sri = Read1302(r_Day); sxi = Read1302(r_xi); writefuhao(); writesfm(0,sshi); writesfm(3,sfen); writesfm(6,smiao); writenyr(0,snian); writenyr(3,syue); writenyr(6,sri); writexi(sxi); delay(500); alarm = 1; delay(500); } vo
33、id Speak2() { alarm=0; delay(500); Normal(); delay(500); Normal(); alarm=1; } void Normal() //正常显示时间功能 { smiao = Read1302(r_Sec); sfen = Read1302(r_Min); sshi = Read1302(r_Hou); snian = Read1302(r_Yea); syue = Read1302(r_Mou); sri = Read1302(r_Day); sxi = R
34、ead1302(r_xi); //读取时间数据 if((nshi==sshi)&&(nfen==sfen)) //闹钟铃响 { for(i=0;i<2;i++) { key5(); if(b==0) { Speak1(); } } } //关闭蜂鸣器 if((sshi==0||sshi==1||sshi==2||sshi==3
35、 ||sshi==4||sshi==5||sshi==6||sshi==7 ||sshi==8||sshi==9||sshi==10||sshi==11 ||sshi==12||sshi==13||sshi==14||sshi==15 ||sshi==16||sshi==1||sshi==18||sshi==19 ||sshi==20||sshi==21||sshi==22||sshi==23) &&(sfen==0)&&(smiao==0)) { Speak2(); //整点报时 } alarm
36、1; //关闭蜂鸣器 writefuhao(); writesfm(0,sshi); writesfm(3,sfen); writesfm(6,smiao); writenyr(0,snian); writenyr(3,syue); writenyr(6,sri); writexi(sxi); } /***********************按键程序*********************************/ void key() //闹钟时的按键功能 { if(k1==0) { delay(1
37、0); if(k1==0) { n++; while(!k1); if(n==1) { write_add(0x0f); write_add(0x80+0x40+4); //写shi } if(n==2) { write_add(0x0f); write_add(0x80+0x40+7); //写fen } if(n==3) {
38、 n=0; nfen=fen; nshi=shi; //确认 write_add(0x0c); //光标不闪烁 } } } if(k2==0) { delay(10); if(k2==0) { while(!k2); if(n==1) { shi++; if(shi==24)
39、 shi=0; writesfm(4,shi); } if(n==2) { fen++; if(fen==60) fen=0; writesfm(7,fen); } } } if(k3==0) { delay(10); if(k3==0) { while(!k3); if(n==1)
40、 { shi--; if(shi==-1) shi=23; writesfm(4,shi); } if(n==2) { fen--; if(fen==-1) fen=59; writesfm(7,fen); } } } } void ke
41、y1(void) { if(k1==0) //设置光标所在位置 { delay(10); //去抖 if(k1==0) { num++; while(!k1); if(num==1) { write_add(0x0f); //显示光标并闪烁 write_add(0x80+0x40+6); } if(num==2) { write_a
42、dd(0x0f); //显示光标并闪烁 write_add(0x80+0x40+3); } if(num==3) { write_add(0x0f); //显示光标并闪烁 write_add(0x80+0x40+0); } if(num==4) { write_add(0x0f); //显示光标并闪烁
43、 write_add(0x80+0x00+6); } if(num==5) { write_add(0x0f); //显示光标并闪烁 write_add(0x80+0x00+3); } if(num==6) { write_add(0x0f); //显示光标并闪烁 write_add(0x
44、80+0x00+0); } if(num==7) { write_add(0x0f); //显示光标并闪烁 write_add(0x80+0x00+11); } if(num==8) { num=0; write_add(0x0c);//关闭光标 menu=0; write_add(0x01
45、); //清屏 } } } } void key2(void) { Write1302(w_protect,0x00); //禁止写保护 if(k2==0) //实现加法 { delay(10); if(k2==0) { while(!k2); if(num==1) { miao++; if(miao
46、60) { miao=0; } writesfm(6,miao); //将miao转换成BCD码 Write1302(w_Sec,(miao/10)*16+miao%10); } if(num==2) { fen++; if(fen==60) {
47、 fen=0; } writesfm(3,fen); Write1302(w_Min,(fen/10)*16+fen%10); } if(num==3) { shi++; if(shi==24) { shi=0;
48、 } writesfm(0,shi); Write1302(w_Hou,(shi/10)*16+shi%10); } if(num==4) { ri++; if(ri==30) { ri=0; }
49、 writenyr(6,ri); Write1302(w_Day,(ri/10)*16+ri%10); } if(num==5) { yue++; if(yue==13) { yue=1; }
50、 writenyr(3,yue); Write1302(w_Mou,(yue/10)*16+yue%10); } if(num==6) { nian++; if(nian==100) { nian=0;






