单片机制作万历方案.doc

上传人:仙人指路1688 文档编号:4147282 上传时间:2023-04-07 格式:DOC 页数:26 大小:97KB
返回 下载 相关 举报
单片机制作万历方案.doc_第1页
第1页 / 共26页
单片机制作万历方案.doc_第2页
第2页 / 共26页
单片机制作万历方案.doc_第3页
第3页 / 共26页
单片机制作万历方案.doc_第4页
第4页 / 共26页
单片机制作万历方案.doc_第5页
第5页 / 共26页
点击查看更多>>
资源描述

《单片机制作万历方案.doc》由会员分享,可在线阅读,更多相关《单片机制作万历方案.doc(26页珍藏版)》请在三一办公上搜索。

1、单片机制作万年历方案1.1 本课题主要的研究工作本项目是一种基于AT89C51片机的万年历设计,本方案以AT89C51片机作为主控核心,与时钟芯片DS1302、温度DS18B20按键、LCD1602液晶显示器组成硬件系统。在硬件系统中设有独立按键和LCD1602显示器,能显示丰富的信息,根据使用者的需要可以随时对时间进行更改,读取方便、显示直观。当程序执行后,LCD显示即时时间、年月日、星期。设置4个操作键:K1:选择键;K2:加键;K3:减键;K4:确定键。1本设计的主要内容:(1)熟悉万年历各模块的工作原理;(2)选择适当的芯片和元器件,确定系统电路,绘制电路原理图,尤其是各接口电路;(3

2、)熟悉单片机使用方法和C语言,编写出相应模块的应用程序;(4)分别在各自的模块中调试出对应的功能,在Proteus软件上进行仿真,并实现各种功能。2设计目标:万年历实现以下三个功能:(1)具有年、月、日、星期、时、分、秒等功能;(2)具备年、月、日、星期、时、分、秒校准功能,具备自动调节闰年的功能;(3)具有与即时时间同步的功能。(4)具有温度显示功能本设计是基于51系列的单片机进行的电子万年历设计,可以显示年月日时分秒及周信息,具有可调整日期和时间功能。1.2 系统硬件概述本电路是以STC89C51单片机为控制核心,该芯片具有在线编程功能,功耗低,能在3.3V的超低压下工作;时钟芯片采用DS

3、1302,它是一款高性能、低功耗、自带RAM的实时时钟芯片,具有掉电自动保存功能。可自动对秒、分、时、日、周、月、年进行计数,具有闰年补偿功能,而且精度高位的RAM做为数据暂存区,工作电压2.5V5.5V范围内,2.5V时耗电小于300nA。显示模块采用1602显示屏,它内置192种字符,可显示32个符号或数字,清晰可见,而且功率消耗小寿命长抗干扰能力强。其工作电压为5v。1.3单片机主控制模块的设计一个典型的单片机最小系统一般由时钟电路、复位电路、电源指示灯和外部扩展接口等部分组成。单片机的最小系统如下图所示,单片机的XTAL0和XTAL1引脚用于连接晶振电路。RESET为复位引脚,连接复位

4、电路,用于初始化MCU1.4显示模块的设计本设计中要对时间、温度进行显示,液晶显示屏1602模块作为输出。1602字符型LCD通常有14条引脚线或16条引脚线的LCD,多出来的2条线是背光电源线。它可以显示两行,每行16个字符,采用单+5V电源供电,外围电路配置简单。1602液晶模块内部的字符发生存储器已经存储了160个不同的点阵字符图形,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。LCD1602引脚功能:1VSS一般接地2VDD接电源(+5V)3V0液晶显示器对比度调整端。

5、4RSRS为寄存器选择。5R/WR/W为读写信号线。6EE(或EN)端为使能(enable)端,下降沿使能。1602主要管脚介绍:V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高,对比度过高时会产生鬼影使用时可以通过一个10K的电位器调整对比度。RS为寄存器选择端,高电平时选择数据寄存器,低电平时选择指令寄存器。RW为读写信号线端,高电平时进行读操作,低电平时进行写操作。当RS和RW共同为低电平时可以写入指令或者显示地址;当RS为高电平RW 为低电平时可以写入数据。E为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。将L1602的RS端和P2.0,R/W端和P2

6、.1, E 端和P2.2相连,当RS=0时,对LCD1602写入指令;当RS=1时,对LCD1602写入数据。当R/W端接高电平时芯片处于读数据状态,反之处于写数据状态,E端为使能信号端。当R/W为高电平,E端也为高电平,RS为低电平时,液晶显示屏显示需要显示的示数。显示模块电路图如图3所示:图31.5独立式键盘设计独立式键盘每个键单独占用一根I/O口线。键盘的工作方式可分为编程控制方式和中断控制方式。CPU在一个工作周期内,利用完成其他任务的空余时间,调用键盘扫描子程序,经程序查询,若无键操作,则返回;若有键操作,则进而判断是哪个键,并执行相应的键处理程序。这种方式为编程扫描方式。由于单片机

7、在正常应用过程中,可能会经常进行键操作,因而编程控制方式使CPU经常处于工作状态, 在进行本次设计中,只涉及到了选择、加、减、确定四个功能。因此采用独立式键盘。2电路设计框图显示模块LCD1602温度模块DS18B20AT89C51主控制模 块 键盘模块时钟模块DS13023程序流程框图初始化开始读、写日期、时间和温度分离日期时间温度显示值显示子程序日期、时间修改子程序定时闹铃子程序农历自动更新子程序返 回闰月子程开始控制键有效,进入年调整程序等待按键程序加键有效减键有效年加1减加1控制键有效,进入日调整程序等待按键程序加键有效减键有效日加1日减1控制键有效,进入月调整程序等待按键程序加键有效

8、减键有效月加1月减1控制键有效,进入星期调整程序等待按键程序加键有效减键有效星期加1星期减1控制键有效,进入分钟调整程序等待按键程序加键有效减键有效分钟加1分钟减1按键有效,跳出时间调整程序,进入主循环程序控制键有效,进入小时调整程序等待按键程序加键有效减键有效小时加1小时减14电路图:5元件清单:元件个数元件个数DS13201DS18B201LCD1602(显示器)1晶振32.768KHZ1瓷片电容220PF13V纽扣电池及底座1按键44.7K(9针)排阻1可调电阻1K26:程序设计1602液晶万年历程序-显示年月日,时间,温度(续) /*键盘识别程序*uchar key(void)ucha

9、r i,j;K1=0;i=P2;delay_key(500);j=P2;K1=1;if(i=j)switch(j) case 0xee: return(j);break; case 0xed: return(j);break; case 0xeb: return(j);break; case 0xe7: return(j);break; K2=0; i=P2; delay_key(500); j=P2; K2=1; if(i=j) switch(j) case 0xde: return(j);break; case 0xdd: return(j);break; case 0xdb: retur

10、n(j);break; case 0xd7: return(j);break; /=模式的判断=uchar key_only(void) /此程序延时较长uchar i,j;K1=0;i=P2;delay_key(500);j=P2;K1=1;if(i=j)if(j=0xee)while(j=0xee) /直到放手 delay_key(50000); j=P2; delay_key(10000); return(0xee);elsereturn(0);elsereturn(0);/=指针移动=void cursor_shift_right()if(addr=0x80+0x0f)addr=0x8

11、0+0x3f;elseif(addr=0x80+0x4f)addr=0x7f;LCD_Write(LCD_COMMAND, +addr);/rightvoid cursor_shift_left() if(addr=0x80)addr=0x80+0x50;elseif(addr=0x80+0x40)addr=0x80+0x10;LCD_Write(LCD_COMMAND, -addr);/left/*模式判断*void mode(void)if(key_only()=0xee) +done; if(done=4) done=0; /=警报声,分长短音=void alarm_voice(ucha

12、r i) uchar n; if(i=0)n=8;for(;n0;n-) DS1302_GetTime(&CurrentTime); /获取时钟芯片的时间数据 TimeToStr(&CurrentTime); /时间数据转换液晶字符 DateToStr(&CurrentTime); /日期数据转换液晶字符 ReadTemp(); /开启温度采集程序 temp_to_str(); /温度数据转换成液晶字符 GotoXY(10,1); /液晶字符显示位置 Print(TempBuffer); /显示温度 GotoXY(0,1); Print(CurrentTime.TimeString); /显示

13、时间 GotoXY(0,0); Print(CurrentTime.DateString); /显示日期 GotoXY(15,0); Print(week_value); /显示星期 voice=voice;else if(i=1)n=10;for(;n0;n-) show_time(); voice=voice;else if(i=2)n=20;for(;n0;n-) DS1302_GetTime(&CurrentTime); /获取时钟芯片的时间数据 TimeToStr(&CurrentTime); /时间数据转换液晶字符 ReadTemp(); /开启温度采集程序 temp_to_str

14、(); /温度数据转换成液晶字符 GotoXY(10,1); /液晶字符显示位置 Print(TempBuffer); /显示温度 GotoXY(0,1); Print(CurrentTime.TimeString); /显示时间 voice=voice;else if (i=3)n=16;for(;n0;n-) delay_key(10000); voice=voice;/*主函数*/main() uchar i,num,alarm_count=0;uchar code table=welcome chen611b; uchar code table1=clock+temp v1.0 ;fl

15、oat Current_temp,max_temp_count,min_temp_count; guandz(); guanled(); LCD_Initial(); /液晶初始化Init_DS18B20( ) ; /DS18B20初始化Initial_DS1302(); /时钟芯片初始化max_temp_value(); /上限min_temp_value(); /下限done=2; /进入默认液晶显示/=LCD_Write(LCD_COMMAND,0x80+0x10);for(num=0;num16;num+) LCD_Write(LCD_DATA,tablenum); delay_key

16、(50);LCD_Write(LCD_COMMAND,0x80+0x51);for(num=0;num15;num+) LCD_Write(LCD_DATA,table1num); delay_key(50);for(num=0;num16;num+) LCD_Write(LCD_COMMAND,0x18); delay_key(300000);delay_key(50000000);/=while(1) alarm_count=0; mode();delay_key(20000);/*闹钟* if(done=0)LCD_Write(LCD_COMMAND, 0x01); GotoXY(0,0

17、); LCD_Write(LCD_COMMAND,0x80); Print( alarm); /这个问题一直想不通,清屏后,为什么不会在指定的地方写,我只好在前面加空格了 GotoXY(0,1); Print(alarm_TimeString); /显示时间 while(done=0) mode(); LCD_SetDisplay(LCD_SHOW|LCD_FLASH); if(key()=0xed) cursor_shift_left(); delay_key(20000); else if(key()=0xd7) cursor_shift_right(); delay_key(20000)

18、; else if(key()=0xdd) alarm_add_time(); LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); /开启显示, 无光标 GotoXY(0,1); Print(alarm_TimeString); /显示时间 LCD_Write(LCD_COMMAND,addr); LCD_SetDisplay(LCD_SHOW|LCD_FLASH); delay_key(8000); else if(key()=0xdb) alarm_sub_time(); LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); /开启显示

19、, 无光标 GotoXY(0,1); Print(alarm_TimeString); /显示时间 LCD_Write(LCD_COMMAND,addr); LCD_SetDisplay(LCD_SHOW|LCD_FLASH); delay_key(8000); mode(); /*调整时间*if(done=1) /进入调整模式 DS1302_GetTime(&ad_CurrentTime); show_time_mode(); addr=0x80+0x0f; LCD_SetDisplay(LCD_SHOW|LCD_FLASH); while(done=1) mode(); if(key()=

20、0xed) cursor_shift_left(); delay_key(20000); else if(key()=0xd7) cursor_shift_right(); delay_key(20000); else if(key()=0xdd) add_time(&ad_CurrentTime); LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); /开启显示, 无光标 show_time_mode(); LCD_Write(LCD_COMMAND,addr); LCD_SetDisplay(LCD_SHOW|LCD_FLASH); delay_key(1000

21、); else if(key()=0xdb) sub_time(&ad_CurrentTime); LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); /开启显示, 无光标 show_time_mode(); LCD_Write(LCD_COMMAND,addr); LCD_SetDisplay(LCD_SHOW|LCD_FLASH); delay_key(1000); if(key()=0xeb) ad_DS1302(); LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); show_time(); addr=0x80+0x0f; mo

22、de();/*正常时间温度显示*while(done=2) mode(); LCD_Write(LCD_COMMAND, 0x01); LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); show_time(); /液晶显示数据 addr=0x80+0x0f; for(i=0;i=max_temp_count) alarm_voice(2); else if(Current_temp=min_temp_count) alarm_voice(0); mode();/=上下限温度设置=if(done=3)LCD_Write(LCD_COMMAND, 0x01); LCD

23、_SetDisplay(LCD_SHOW|LCD_FLASH);GotoXY(0,0);LCD_Write(LCD_COMMAND,0x80); Print( max_temp); /这个问题一直想不通,清屏后,为什么不会在指定的地方写,我只好在前面加空格了GotoXY(12,0); Print(max_temp); GotoXY(0,1); Print(min_temp); GotoXY(12,1); /液晶字符显示位置 Print(min_temp);addr=0x80+0x4f; while(done=3) mode(); LCD_SetDisplay(LCD_SHOW|LCD_FLAS

24、H); if(key()=0xed) cursor_shift_left(); delay_key(20000); else if(key()=0xd7) cursor_shift_right(); delay_key(20000); else if(key()=0xdd) if(addr=0x80+0x0f|addr=0x80+0x0c|addr=0x80+0x0d) max_tempaddr-0x80-12+; else if(addr=0x80+0x4f|addr=0x80+0x4c|addr=0x80+0x4d) min_tempaddr-0x80-0x40-12+; delay_ke

25、y(30000); else if(key()=0xdb) if(addr=0x80+0x4f|addr=0x80+0x4c|addr=0x80+0x4d) min_tempaddr-0x80-0x40-12-; else if(addr=0x80+0x0f|addr=0x80+0x0c|addr=0x80+0x0d) max_tempaddr-0x80-12-; delay_key(30000); LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); /开启显示, 无光标 GotoXY(12,0); Print(max_temp); LCD_Write(LCD_CO

26、MMAND,addr); GotoXY(12,1); /液晶字符显示位置 Print(min_temp); LCD_Write(LCD_COMMAND,addr); LCD_SetDisplay(LCD_SHOW|LCD_FLASH); delay_key(1000); max_temp_count=max_temp0*10+max_temp1+max_temp3/10; min_temp_count=min_temp0*10+min_temp1+min_temp3/10; if(max_temp_countmin_temp_count) LCD_Write(LCD_COMMAND, 0x01); LCD_Write(LCD_COMMAND,0x80); Print( error! readjust); /这个问题一直想不通,清屏后,为什么不会在指定的地方写,我只好在前面加空格了 alarm_voice(3); done=3;

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 办公文档 > 其他范文


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号