单片机电子时钟设计报告_第1页
单片机电子时钟设计报告_第2页
单片机电子时钟设计报告_第3页
单片机电子时钟设计报告_第4页
单片机电子时钟设计报告_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、电 子 时 钟 实 验 报 告 全部代码在文档末尾:51单片机,lcd1602液晶 显示屏平台下编程实现,可直接编译运行 目录:一, 实验目的1二,实验要求1三,实验基本原理 2四,实验设计分析2五,实验要求实现2a.电路设计31 .整体设计32 .分块设计32.1 输入部分32.2 输出部分32.3 晶振与复位电路 3b.程序设计38.1 程序总体设计38.2 程序主要模块3五.实验总结及感想5一,实验目的20世纪末,电子技术获得了飞速的发展,在其推动下,现代电子产品几乎渗透了社会的各个领域,有力地推动了社会生产力的发展和社会信息化程度的提高,同时也使现代电子产品性能进一步提高,产品更新换代

2、的节奏也越来越快。现代生活的人们越来越重视起了时间观念, 可以说是时间和金钱划上了等号。 对于那 些对时间把握非常严格和准确的人或事来说,时间的不准确会带来非常大的麻烦, 所以电子钟是以其小巧,价格低廉,走时精度高,使用方便,功能多,便于集成化而受广大消费 的喜爱,得到了广泛的使用。1 .学习8051定时器时间计时处理、按键扫描及lcd液晶显示的设计方法。2 .设计任务及要求利用实验平台上 lcd1602液晶显示屏,设计带有闹铃功能的数字时钟二,实验要求a.基本要求:1 .在lcd1602液晶显示屏上显示当前日期,时间。2 .利用按键可对时间及闹玲进行设置,并可显示设置闹玲的时间。闹玲时间到蜂

3、鸣器发出声响,一分 钟后闹铃停止。b.扩展部分:1 .日历功能(能对年,月,日,星期进行显示,分辨平年,闰年以及各月天数,并调整)实现年月日时 分秒的调整,星期准确的随着日期改变而改变进行显示。2 .定时功能(设定一段时间长度,定时到后,闹铃提示)c.可扩展部分:1 .闹铃重响功能(闹铃被停止后,以停止时刻开始,一段时间后闹铃重响,且重响时间的间隔可调)2 .可进行备忘录提示,按照年月日,可在设定的某年某月进行闹铃提示。三,实验基本原理利用单片机定时器完成计时功能,定时器0计时中断程序每隔 0.05s中断一次并当作一个计数,设定定时1秒的中断计数初值为 20,每中断一次中断计数初值加 1,当减

4、到20时,则表示1s到了,秒变 量加1,同理再判断是否 1min钟到了,再判断是否 1h到了,是否一天到了,是否一个月到了,是否一 年到了。将时间在lcd液晶屏上显示,降低了程序的编写难度。lcd的固定显示特性是我们省去了数码管的动态扫描显示。四,实验设计分析针对要实现的功能,采用 at89s52片机进彳t设计,at89s52单片机是一款低功耗,高性能 cmos8 位单片机,片内含4kb!e线可编程(isp)的可反复擦写1000次的flash只读程序存储器,器件采用高密 度、非易失性存储技术制造,兼容标准mcs-51指令系统及80c51引脚结构。这样,既能做到经济合理又能实现预期的功能。在程序

5、方面,采用分块设计的方法,这样既减小了编程难度、 使程序易于理解,又能便于添加各项功能。程序可分为闹钟的声音程序、时间显示程序、日期显示程序,秒表显示程序,时间调整程序、闹 钟调整程序、定时调整程序,延时程序等。运用这种方法,关键在于各模块的兼容和配合,若各模块不 匹配会出现意想不到的错误。首先,在编程之前必须了解硬件结构尤其是各引脚的用法,以及内部寄存器、存储单元的用法,否则,编程无从下手,电路也无法设计。这是前期准备工作。第二部分是硬件部分:依据想要的功能分块设计设计,比如输入需要开关电路,输出需要显示驱动电路和数码管电路等。第三部分是软件部分:先学习理解c语言的编程方法再根据设计的硬件电

6、路进行分块的编程调试,最终完成程序设计。第四部分是软件画图部分:设计好电路后进行画图,包括电路图和仿真图的绘制。第五部分是软件仿真部分:软硬件设计好后将软件载入芯片中进行仿真,仿真无法完成时检查软件程序和硬件电路并进行修改直到仿真成功。第六部分是硬件实现部分:连接电路并导入程序检查电路,若与设计的完全一样一般能实现想要的功能。最后进行功能扩展,在已经正确的设计基础上,添加额外的功能!五,实验要求实现a.电路设计1.整体设计此次设计主要是应用单片机来设计电子时钟,硬件部分主要分以下电路模块:显示电路用lcd1602显示,年份,月份,星期,小时、分钟和秒(日),使电路更加简单。单片机采用 at89

7、s51系列,这种单片机应用简单,适合电子钟设计。电路的总体设计框架如下:2.2 输出部分本电路的输出信号lcd勺写入命令和写入数据,闹铃脉冲信号闹铃由p1.5端输出,模块如下:日期时间由lcd1602俞出,模块如下:2.3 晶振与复位电路本实验单片机时钟用内部时钟,模块如下:复位电路为手动复位构成,模块如下:b.程序设计b.1程序总体设计本实验用汇编程序完成.程序总的流程图如下:b.2程序主要模块中断服务程序:/*一秒定时中断函数*/void timer0() interrupt 1 using 1 et0=0;/关闭定时器t0中断允许位tr0=0;/关闭定时器t0jiamiao+; th0=

8、(65536-50000)/256;/设定每次中断间隔 50mstl0=(65536-50000)%256; tr0=1;/启动定时器t0et0=1;/打开定时器t0中断允许位 本实验中,计数器t0有运用,其中t0中断为时钟定时所用,t1中断用于秒表的准确性保证。t0的定时长度为0.05s,工作于方式1,计数1次,时长1us,故计数器计数20次,进入中断,装满定时器需要0.05s 的时间,从而20次中断为一秒,一秒之后,判断是否到60秒,若不到则秒加一,然后返回,若到,则秒赋值为0,分加一,依次类推。包括日期显示的功能也是如此。另外,由于要实现倒计时功能,因此在 中断程序中还要加入加一的寄存器

9、,需要时将其进行显示。程序中日历的实现较为复杂,要考虑平年,闰年,特殊的2月,每月的天数的不尽相同。具体的逻辑判断方法为:首先,要考虑年份是不是闰年,闰年的判断方法是:将年份除以100,若能整除,则将年份除以400,若还能整除,则为闰年,若不能,则为平年;若不能被100整除,则判断是否能被4整除,若能,则为闰年,若不能则为平年。只有2月与平、闰年相关,因此在闰年和平年的子程序中,要判断是不是2月,若是则在相应的年中进行日期的增加,若不是则转入平时的月份。其中 1、3、5、7、8、10、 12月是每月31天,4、6、9、11月为每月30天。显小子程序:/*刷新液晶屏显示内容子函数 */void

10、brush_lcd() static uchar old_second=0x01;if(dis_val6!=old_second)old_second=dis_val6;in_command(0x80);in_data(2);/in_data(0);/in_data(num_tabdis_val0/16);in_data(num_tabdis_val0%16);in_data(-);in_data(num_tabdis_val1/16);in_data(num_tabdis_val1%16);in_data(-);in_data(num_tabdis_val2/16);in_data(num_

11、tabdis_val2%16);in_data();in_data();/刷新原来的秒为新秒值/设定第一行字符串起始显示位置年的千位年的百位/显示年/显示分隔符/显示月/显示分隔符/显示日/显示分隔符/显示分隔符week_disp(dis_val3);in_data();in_command(0xc0);in_data(-);in_data(-);in_data(-);in_data(-);in_data(num_tabdis_val4/16);in_data(num_tabdis_val4%16); in_data(:);in_data(num_tabdis_val5/16);in_data

12、(num_tabdis_val5%16); in_data(:);in_data(num_tabdis_val6/16);in_data(num_tabdis_val6%16);in_data(-);in_data(-);in_data(-);in_data(-);/lcd1602显示星期值/显示分隔符/设定第二行字符串起始显示位置/显示分隔符/显示分隔符/显示分隔符/显示分隔符/显示时/显示分隔符/显示分/显示分隔符/显示秒/显示分隔符/显示分隔符/显示分隔符/显示分隔符本程序通过keil单片机开发平台实现程序的编译,链接,生成he双件。程序再编译过程中可以发现错位,并及时改正,在设计时非常

13、重要,使错误被扼杀在摇篮中。五.实验总结及感想一分耕耘,一分收获。只有亲自用实践来验证这句话,在能得其要领。经过这次单片机课程设计,我从一个单片机实践的门外汉, 已经越升为略知一二的新手。 虽然还有很多有关单片机的应用有待学习,但万变不离其宗,只要深入了解单片的原理,全部知识点,各个细节,一切设计皆有可能。在实验的开始几天,基本上没有收获,不知何从下手,不知所措。为了看得更远,不妨站在前人的肩膀上,我在整体思路模糊的情况下,在网上大量招资粮,各种与电子时钟相关的文章,我阅读了不少。随着涉猎的点滴积累,我对电子时钟的设计方案已经慢慢酝酿而成。有了方向和不少知识储备后,在接下来的几天,几乎每天都有

14、突破, 虽然有时只是一句程序的修改或诞生,但那种收获的感觉很暖人心。实验中遇到了不少问题,接下来总结一下,共同探讨。1, p0 口开关问题。p0口比较特殊,它存在高阻态,要使其输入不是高电平就是低电平,就要接上拉电阻,给其高电平输入。以上就是实验中遇到的主要问题,基本上都找到了相应的解决之道。整个实验的过程就是一个解决问题的过程,每天都解决一些问题,我的实验也就解决了,当然结果不重要,功利化的追求结果,会使人浮躁,还是享受那份疑难迎刃而解的快感吧!全部完整代码:此代码未经本人优化,可以根据自己的需求优化代码。盗版不究,可直接引用。/*/基于stc89s52单片机以及液晶1602显示的万年历项目

15、/*/ #include#include #define uchar unsigned char#define uint unsigned int/*液晶 1602 相关参数 */#define data_port p0 sbit rs=p1a0;时选择数据寄存器)sbit rw=p1a1;读出)sbit en=p1a2;接口接通)液晶屏指令、数据通信接口液晶屏寄存器选择接口( rs=0时选择指令寄存器,液晶屏读写选择接口( rw=0时选择写入,rw=1液晶屏使能接口( en=0时通信接口中断,en=1rs=1时选择时通信uchar code line1_str尸-welcome!-;/液晶屏

16、第一行要显示的字符串uchar code line2_str口= made by:mcu ;液晶屏第二行要显示的字符串/*按键设置的相关参数*/sbit timer=p1a5;sbit sound=p3a4;uchar sflag=0,ssflag=0;sbit set_key=p3a7;sbit up_key=p3a6;sbit cancle_key=p3a5;uchar set=0;uchar flag=0;ucharyear=0x00;uchar month=0x01;uchar day=0x01;uchar week=0x06;uchar hour;uchar minite;uchar

17、 second;uchar jiamiao=0;uchar fen1,fen2;uchar shi1,shi2;液晶屏要显示的数字表/蜂鸣器/进入闹铃设置状态键闹铃设置标志位;闹铃工作标志位/进入设置/加号键完成设置键是否进行了设置设置选择标志年寄存器月寄存器日寄存器/星期寄存器时寄存器分寄存器秒”寄存器加秒参数/ (数据交换)分定时寄存器/ (数据交换)时定时寄存器uchar dis_val7=0x00,0x01,0x01,0x06,0x00,0x00,0x00;/依次存储:年,月,日,星期,时,分,秒/*子函数部分*/初始化1602液晶欢迎界面向液晶屏输入命令void lcd_int();

18、void welcome。;void in_command(uchar com);void in_data(uchar dat);void delay(uint ms);void key();uchar calculate_week();void week_disp(uchar x);void lcd_disp_string(uchar str);void brush_lcd();void run();向液晶屏输入数据延时函数按键设置函数星期计算函数/lcd1602显示星期值子函数声明液晶屏显示一串字符子函数声明刷新液晶屏显示内容子函数声明万年历正常运行函数/*/tmod=0x01;th0=(

19、65536-50000)/256;tl0=(65536-50000)%256;jiamiao=1;ea=1;et0=1;void main()/0000 0001使用定时器t0的模式1 (16位模式)设定每次中断间隔 50ms打开总中断允许打开定时器t0中断允许位启动定时器t0tr0=1;lcd_int();welcome。;delay(1000);while(1) key();if(jiamiao=20) second+;dis_val6=(second/10)4)|(second%10);刷新秒jiamiao=0;run();if(flag=0) if(dis_val0=0x00 & di

20、s_val1=0x01 & dis_val2=0x01)/2000 年 1 月 1 日为星期六 dis_val3=0x06; brush_lcd();刷新液晶屏显示内容 if(hour=shi2 & minite=fen2 &ssflag=1) timer=0; elsetimer=1;/*延时子函数 */void delay(uint ms) uchar i;while(ms-)for(i=0;i=1) days_number=(year-1)/4)+1);从 00 年至u year-1 年的闰年个数days_number=days_number+(year*365);/从 00 年至u y

21、ear-1 年的总天数 else days_number=0;for(i=1;imonth;i+)switch(i)case 1:case 3:case 5:case 7:case 8:case 10:case 12:days_number+=31;/大月 31 天 break;case 4:case 6:case 9:case 11:days_number+=30;/小月 30 天 break;case 2: if(year%4=0) 闰年 2 月 29 天 days_number+=29;else平年2月28天days_number+=28; break;days_number+=day;

22、加上本月日期if(days_number+5)%7=0)计算现在的星期值,并返回其值return(7);elsereturn(days_number+5)%7);/*lcd1602显示星期值子函数*/void week_disp(uchar x)switch(x)case 1: lcd_disp_string(mon); 显示星期一 break;case 2: lcd_disp_string(tue); 显示星期二 break;case 3: lcd_disp_string(wed); 显示星期三 break;case 4: lcd_disp_string(thu); 显示星期四 break;

23、case 5: lcd_disp_string(fri); 显示星期五 break;case 6: lcd_disp_string(sat); 显示星期六 break;case 7: lcd_disp_string(sun); 显示星期日break;/*按键设置函数*/void key()if(set_key=0)delay(5);if(set_key=0)et0=0;tr0=0;if(flag6)flag+; elseflag=0; switch(flag) case 0: if(set=1)set=0;/检测设置键是否按下延时消抖打开定时器t0中断允许位启动定时器t0检测时间是否更改时间更

24、改标志复位dis_val0=(year/10)4)|(year%10); 刷新年dis_val1=(month/10)4)|(month%10);刷新月dis_val2=(day/10)4)|(day%10);刷新日dis_val3=week;刷新星期dis_val4=(hour/10)4)|(hour%10);刷新时dis_val5=(minite/10)4)|(minite%10);刷新分dis_val6=(second/10)4)*10)+(dis_val0&0x0f);预设调节变量初始值为当month=(dis_val14)*10)+(dis_val1&0x0f);day=(dis_v

25、al24)*10)+(dis_val2&0x0f);hour=(dis_val44)*10)+(dis_val4&0x0f);minite=(dis_val54)*10)+(dis_val5&0x0f);second=(dis_val64)*10)+(dis_val6&0x0f);break;case 2: in_command(0x86);/设定显示(光标)位置-月低位闪烁break;case 3: in_command(0x89);/设定显示(光标)位置-日低位闪烁break;case 4: in_command(0xc5);设定显示(光标)位置-时低位闪烁break; case 5: i

26、n_command(0xc8);设定显示(光标)位置-分低位闪烁break; case 6: in_command(0xcb); 设定显示(光标)位置-秒低位闪烁 break; while(set_key=0); if(up_key=0 & flag!=0)检测设置时间启动时,上升键是否按下 delay(5);延时消抖if(up_key=0) switch(flag) case 1: if(sflag=1) break; if(year28) day=28; in_command(0x88);设定显示(光标)位置-日高位in_data(num_tabday/10); 修正日 in_data(n

27、um_tabday%10); week=calculate_week(); / 计算星期值 in_command(0x8c);/设定显示(光标)位置-星期week_disp(week); /lcd1602 显示星期值 in_command(0x82);/设定显示(光标)位置-年高位in_data(num_tabyear/10); 显示正在调节的年 in_data(num_tabyear%10); in_command(0x83);/设定显示(光标)位置一年低位闪烁break; case 2: if(sflag=1) break; if(month30) day=30;in_command(0x

28、88);设定显示(光标)位置-日高位 in_data(num_tabday/10); 修正日 in_data(num_tabday%10);if(month=2) if(year%4!=0)/ 平年 if(day28) day=28; in_command(0x88);设定显示(光标)位置-日高位in_data(num_tabday/10); 修正日 in_data(num_tabday%10);else闰年 if(day29) day=29; in_command(0x88);设定显示(光标)位置-日高位in_data(num_tabday/10); 修正日 in_data(num_tabd

29、ay%10); week=calculate_week();/ 计算星期值in_command(0x8c);设定显示(光标)位置-星期week_disp(week); /lcd1602 显示星期值 in_command(0x85);设定显示(光标)位置-月高位in_data(num_tabmonth/10); 显示正在调节的月 in_data(num_tabmonth%10); in_command(0x86);设定显示(光标)位置-月低位闪烁break; case 3: if(sflag=1) break; if(month=4 | month=6 | month=9 | month=11)

30、 if(day30)day+; elseday=1;else if(month=2) if(year%4!=0)/ 平年if(day28)day+; elseday=1; else闰年if(day29)day+; elseday=1;elseif(day31)day+; elseday=1;week=calculate_week();/ 计算星期值in_command(0x8c);设定显示(光标)位置-星期week_disp(week); /lcd1602 显示星期值in_command(0x88);设定显示(光标)位置-日高位in_data(num_tabday/10); 显示正在调节的日in_data(num_tabday%10);in_command(0x89);设定显示(光标)位置-日低位闪烁break;case 4: if(hour23)if(sflag=1)完成闹钟状态下的数值变换,并保存设置前的状态shi1=hour;hour+;shi2=

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论