6、用DS1302与LCD1602可调数字万年历实验设计报告
基于DS1302和LCD1602的可调数字钟
学习情境2-可调式数字钟之基于DS1302和LCD1602的可调数字钟☆点名,复习1、DS1302的引脚及其功能,以及DS1302与单片机的硬件连接?2、如何对DS1302读写数据,如何得到DS1302的时钟?☆新课讲授2.3 基于DS1302与LCD1602设计的可调数字钟上堂课程我们学会了使用DS1302,知道了如何在单片机系统中的连接,也详细的学习了如何得到DS1302的时钟,并且我们使用了16个数码管把年月日和时分秒实时地显示出来。
但数码管的显示毕竟有其自身的缺陷,现在在工业控制的各个环节,都使用液晶进行人机联系。
在日常生活中,我们对液晶显示器并不陌生。
液晶显示模块已作为很多电子产品的通用器件,如在计算器、万用表、电子表及很多家用电子产品中都可以看到,显示的主要是数字、专用符号和图形。
在单片机的人机交流界面中,一般的输出方式有以下几种:发光管、LED 数码管、液晶显示器。
发光管和LED数码管比较常用,软硬件都比较简单,在单片机系统中应用液晶显示器作为输出器件有以下几个优点:(1)显示质量高,由于液晶显示器每一个点在收到信号后就一直保持那种色彩和亮度,恒定发光,而不像阴极射线管显示器(CRT)那样需要不断刷新新亮点。
因此,液晶显示器画质高且不会闪烁。
(2)数字式接口,液晶显示器都是数字式的,和单片机系统的接口更加简单可靠,操作更加方便。
(3)体积小、重量轻,液晶显示器通过显示屏上的电极控制液晶分子状态来达到显示的目的,在重量上比相同显示面积的传统显示器要轻得多。
(4)功耗低,相对而言,液晶显示器的功耗主要消耗在其内部的电极和驱动IC上,因而耗电量比其它显示器要少得多。
2.3.1 LCD1602技术资料2.3.1.1 液晶显示简介1、液晶显示原理:液晶显示的原理是利用液晶的物理特性,通过电压对其显示区域进行控制,有电就有显示,这样即可以显示出图形。
液晶显示器具有厚度薄、适用于大规模集成电路直接驱动、易于实现全彩色显示的特点,目前已经被广泛应用在便携式电脑、数字摄像机、PDA移动通信工具等众多领域。
单片机实训报告万年历
一、实训目的随着科技的发展,单片机在各个领域的应用越来越广泛。
本次实训旨在通过万年历的设计与实现,让学生深入了解单片机的编程与应用,提高学生的实践能力和创新意识。
通过万年历的设计,使学生掌握单片机的基本原理、编程技巧以及相关外设的使用。
二、实训内容本次实训以AT89C51单片机为核心,结合DS1302时钟芯片、LCD1602液晶显示屏和独立键盘,设计并实现一个具有年、月、日、星期、时分秒显示以及闰年判断功能的万年历。
三、实训步骤1. 需求分析- 显示当前日期和时间,包括年、月、日、星期、时分秒。
- 判断闰年,正确显示2月的天数。
- 允许用户通过按键调整日期和时间。
- 具有电源掉电保护功能,保证数据不丢失。
2. 硬件设计- 核心模块:AT89C51单片机- 时钟模块:DS1302时钟芯片,提供精确的日期和时间。
- 显示模块:LCD1602液晶显示屏,用于显示日期、时间和星期。
- 按键模块:独立键盘,用于调整日期和时间。
- 电源模块:锂电池,提供稳定的电源。
3. 软件设计- 主程序:负责初始化硬件、读取时间、显示时间和日期、处理按键输入等。
- 时钟模块:读取DS1302芯片中的时间,并进行处理。
- 显示模块:将时间、日期和星期显示在LCD1602液晶显示屏上。
- 按键处理模块:根据按键输入调整日期和时间。
4. 程序编写- 使用C语言进行程序编写,利用Keil软件进行编译和烧录。
5. 调试与测试- 对程序进行调试,确保功能正常。
- 对万年历进行测试,验证其准确性。
四、实训结果经过设计、编程、调试和测试,成功实现了万年历的功能。
万年历能够准确显示当前日期和时间,并具有闰年判断功能。
用户可以通过按键调整日期和时间,且在电源掉电的情况下,万年历仍能保持时间。
五、实训心得1. 实践出真知:通过本次实训,深刻体会到理论知识与实践应用相结合的重要性。
只有将所学知识运用到实际项目中,才能真正掌握单片机的编程与应用。
(完整word版)万年历(DS1302+LCD1602【程序、仿真、完整】)
基于52单片机的万年历显示(采用实时芯片DS1302芯片+LCD1602液晶显示)仿真图:/************************************************************-- THE LCD1602 DISPLAY LIB -—COPYRIGHT (C) 2014 BY LLH-— ALL RIGHTS RESERVED —-ATTENTION:延时不能过长,否则无法与DS1302同步(最好小于1ms)*************************************************************/#ifndef __LCD1602_DIS_H__#define __LCD1602_DIS_H__#define uint unsigned int#define uchar unsigned charsbit lcd_rs=P2^0;sbit lcd_rw=P2^1;sbit lcd_en=P2^2;/**********延时子程序************/void delay(uint z){uint x,y;for(x=z;x〉0;x—-)for(y=65;y〉0;y--);//60刚好和DS1302同步}/***********写命令子程序**********/void write_com(uchar com){lcd_rs=0;lcd_rw=0;P0=com;delay(1);lcd_en=1;delay(1);lcd_en=0;}/***********写数据子程序**********/void write_data(uchar date){lcd_rs=1;lcd_rw=0;P0=date;delay(1);lcd_en=1;delay(1);lcd_en=0;}/**********初始化子程序************/void init_LCD1602(){lcd_en=0;write_com(0x38); //显示模式设置:16*2显示,5*7点阵,8位数据接口write_com(0x0c); //开显示,不显示光标write_com(0x06); //指针、光标自动加一,整屏不移动write_com(0x80); //初始位置设置}/*********显示子程序***********/void display(uchar *str){while(*str!='\0’){write_data(*str);str++;}}#endifDS1302的H文件:/******************************************************************—— THE DS1302 REAL_TIME LIB —-COPYRIGHT (C) 2014 BY LLH-- ALL RIGHTS RESERVED ——ATTENTION:不能使用(i=0;i<8;i++),否则,液晶无法显示确切的时间(???);星期的显示多了一天(???)********************************************************************/#ifndef __DS1302_REAL_TIME_H__#define __DS1302_REAL_TIME_H__#define uint unsigned int#define uchar unsigned charsbit DS1302_RST=P1^5;sbit DS1302_SCLK=P1^6;sbit DS1302_IO=P1^7;sbit ACC0=ACC^0;sbit ACC7=ACC^7;typedef struct{uchar second;uchar minute;uchar hour;uchar week;uchar day;uchar month;uchar year;uchar date_str[11];uchar time_str[9];}date_time;/**************写数据定义*****************/#define DS1302_SECOND 0x80#define DS1302_MINUTE 0x82#define DS1302_HOUR 0x84#define DS1302_WEEK 0x8A#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8C#define ST 0x00/*************单字节写数据子程序**************/void single_byte_write(uchar date){uchar i;ACC=date;for(i=8;i〉0;i--) //不能使用(i=0;i〈8;i++),否则,液晶只显示00000{DS1302_IO=ACC0;DS1302_SCLK=1;DS1302_SCLK=0;ACC=ACC>>1;}}/*************单字节读数据子程序**************/uchar single_byte_read( ){uchar i;for(i=8;i>0;i--){ACC=ACC>〉1;ACC7=DS1302_IO;DS1302_SCLK=1;DS1302_SCLK=0;}return ACC;}/**************控制字的写入****************/void write_command(uchar addr,uchar dat){DS1302_SCLK=0;DS1302_RST=0;DS1302_RST=1;single_byte_write(addr);single_byte_write(dat);DS1302_SCLK=1;DS1302_RST=0;}/**************读取芯片内部的数据****************/uchar read_data(uchar address){uchar r_data;DS1302_SCLK=0;DS1302_RST=0;DS1302_RST=1;single_byte_write(address|0x01);//若没加(或0x01)ds1302和lcd1602都无法正常显示(?)r_data=single_byte_read();DS1302_SCLK=1;DS1302_RST=0;return r_data;}/************初始化子程序************/void init_DS1302(){uchar temp;temp=read_data(DS1302_SECOND);if(temp&0x80){write_command(0x8e,0x00); //启动读写write_command(0x84,0x00);//设置24小时模式write_command(DS1302_SECOND,ST); //写入当前时间数据}}/*************读取时间、并实现BCD和十进制间的转化***************//****************************************************************十进制转8421编码:32/10 = 3*16= 48(十进制)= 30(16进制)32%10 = 230+2 = 32 * 16 + 32 % 10 = 32(8421编码)(即:a/10*10+a%10)8421编码转十进制:51 / 16 = 5 * 10(16进制) = 50(十进制)51 % 16 = 150 + 1 = 51 / 16 + 51 % 16 = 51(十进制)(即:a/16*10+a%16)*****************************************************************/void get_time(date_time *Time){uchar value;value=read_data(DS1302_SECOND);Time—〉second=(value/16)*10+(value%16);value=read_data(DS1302_MINUTE);Time—〉minute=(value/16)*10+(value%16);value=read_data(DS1302_HOUR);(完整word版)万年历(DS1302+LCD1602【程序、仿真、完整】) Time-〉hour=(value/16)*10+(value%16);value=read_data(DS1302_WEEK);Time—〉week=(value/16)*10+(value%16-1);//星期的显示数值比正确值多一value=read_data(DS1302_DAY);Time-〉day=(value/16)*10+(value%16);value=read_data(DS1302_MONTH);Time—>month=(value/16)*10+(value%16);value=read_data(DS1302_YEAR);Time-〉year=(value/16)*10+(value%16);}/**************年-月-日-星期“字符”显示***************/void date_to_str(date_time *Time){Time-〉date_str[0]=Time-〉year/10+’0’; //加’0’转化成字符Time—〉date_str[1]=Time—〉year%10+’0';Time->date_str[2]='—’;Time->date_str[3]=Time->month/10+'0';Time->date_str[4]=Time-〉month%10+'0’;Time—>date_str[5]=’—’;Time-〉date_str[6]=Time-〉day/10+'0';Time—>date_str[7]=Time—>day%10+’0’;Time-〉date_str[8]=’-’;Time->date_str[9]=Time—〉week%10+’0’;Time-〉date_str[10]='\0';}/**************时-分-秒“字符”显示***************/void time_to_str(date_time *Time){Time—>time_str[0]=Time->hour/10+’0';Time-〉time_str[1]=Time—〉hour%10+’0';Time—>time_str[2]=’-';Time—>time_str[3]=Time—>minute/10+'0’;Time—>time_str[4]=Time—>minute%10+'0’;Time->time_str[5]='—';Time->time_str[6]=Time->second/10+'0';Time->time_str[7]=Time—>second%10+'0';Time-〉time_str[8]=’\0';}#endif万年历C文件:/********************************************************* TITLE: 实时时钟FUNCTION: DS1302+LCD1602显示实时时钟WRITER: LINLIANHUO(完整word版)万年历(DS1302+LCD1602【程序、仿真、完整】) TIME: 2014-07-30REMARK: matters need attention**********************************************************/#include 〈reg51.h〉#include <string.h〉#include ”DS1302。
DS1302设计的可调万年历(实测正常,附有程序)
DS1302设计的可调万年历(实测正常,附有程序)ds1302设计的可调万年历(本制作所用数码管全为共阳数码管)我刚开始想要搞万年历的时候就是玩游戏打听别人的程序,可是辨认出打听了很多都不理想,必须不就没有日历和时间一起表明,必须不就无法阳入时间的,后来我研究了两天,自己终于把程序编成了出。
不好了,废话我就不多说道,本制作我已经把实物搞了出,确保没问题!下面附有仿真图和实物图。
拍摄的效果不够好,但实物是不错的,本人实物中用三级管代替了仿真图的74hc04非门,用哪个都是可以的……请注意:本程序分后两个c文件的,如果不能编成,可以q我:1107588997我轻易播发程序过去给你……软件源程序:(初始化程序只在已经开始时用一次,之后必须把它屏蔽掉)#include#include#includeuchartime_data[7]={0,0,0,0,0,0,0};ucharwrite_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};ucharread_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};voidwrite_ds1302_byte(uchardat){uchari;for(i=0;i<8;i++){sck=0;io=dat&0x01;dat=dat>>1;sck=1;}}voidwrite_ds1302(ucharadd,uchardat){rst=0;_nop_();sck=0;_nop_();rst=1;_nop_();write_ds1302_byte(add);write_ds1302_byte(dat);rst=0;_nop_();io=1;sck=1;}ucharread_ds1302(ucharadd){uchari,value;rst=0;_nop_();sck=0;_nop_();rst=1;_nop_();write_ds1302_byte(add);for(i=0;i<8;i++){value=value>>1;sck=0;if(io)value=value|0x80;sck=1;}rst=0;_nop_();sck=0;_nop_();sck=1;io=1;returnvalue;}voidread_rtc(void){uchari;for(i=0;i<7;i++){time_data[i]=read_ds1302(read_add[i]);}}voidtime_pros(void){nian=time_data[0]/16*10+time_data[0];yue=time_data[2]/16*10+time_data[2];ri=ti me_data[3]/16*10+time_data[3];xi=time_data[1]/16*10+time_data[1];shi=time_data [4]/16*10+time_data[4];fen=time_data[5]/16*10+time_data[5];miao=time_data[6]/1 6*10+time_data[6];}voidmain(){//init_ds1302();//初始化while(1){read_rtc();time_pros();display();button();}}//----------------------------zichengxu.c----------------------------------------------#defineduan1p2#defineduan2p3#defineweip0#defineuintunsignedint#defineucharunsignedcharsbitsck=p1^1;sbitio=p1^0;sbitrst =p1^2;sbitk1=p1^4;sbitk2=p1^5;sbitk3=p1^6;sbitk4=p1^7;ucharshi,fen,miao,nian,yue,ri,xi,menu,y;unsignedcharcodequan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; voidwrite_ds1302_byte(uchardat);voidwrite_ds1302(ucharadd,uchardat);ucharread_ds1302(ucharadd);//voidinit_ds1302(void);//初始化voidread_rtc(void);voidtime_pros(void);voiddisplay(void);voidbutton(void);voiddelay(uintz){ucharx,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}/*(voidinit_ds1302(void)//初始化{write_ds1302(0x8e,0x00);write_ds1302(0x80,0x00);write_ds1302(0x82,0x20);write_ ds1302(0x84,0x09);write_ds1302(0x86,0x25);write_ds1302(0x88,0x12);write_ds1302 (0x8a,0x06);write_ds1302(0x8c,0x10);write_ds1302(0x90,0x01);write_ds1302(0xc0, 0xf0);write_ds1302(0x8e,0x80);}*/voiddisplay(void){wei=0;duan1=quan[2];if(menu==3&&y<80&&k1!=0&&k2!=0&&k3!=0&&k4!=0){duan2=0xff;}elseduan2=quan[shi/10];delay(2);duan1=0xff;duan2=0xff;wei=1;duan1=quan[0];if(menu==3&&y<80&&k1!=0&&k2!=0&&k3!=0&&k4!=0){duan2=0xff;}elseduan2=quan[shi];delay(2);duan1=0xff;duan2=0xff;。
简析基于DS1302和LCD1602的万年历系统设计论文
简析基于DS1302和LCD1602的万年历系统设计论文简析基于DS1302和LCD1602的万年历系统设计论文0引言在日常生活中,无论哪一行业,哪一领域,时间授时都是不可或缺的。
从古老的钟表到现代的电子设备都提供时间授时的功能。
因此,对于单片机学习者来说,设计并实现一款低成本的,有操作性的,提供年,月,日,小时,分,秒,星期等基本计时功能的万年历系统,显得特别实用,特别有意义。
1总体设计及原理图万年历的基本功能一是要提供年月日等基本时间项的授时;二是可以修改时间项。
基于以上两个功能,我们万年历总体设计方案。
万年历有时钟计时模块,显示模块,调整时钟模块和控制器4部分组成。
接下来的任务就是对以上模块进行选型。
低成本,可操作是选型的标准。
对于控制器,选择最常用的C51系列单片机STC89C52。
STC89C52是由宏品科技生产的是一种低功耗8位基于经典C51内核的微处理器,具有8 KhyteFLASH存储器,512 byte RAM , 4 KByte EEPROM , 32位通用IO接口,可以直接用串口下载程序。
时钟模块选择由dallas公司生产的时钟芯片DS1302,DS1302是一款支持年月日,小时分秒,星期,闰年补偿的实时时钟芯片;其简单三线结构可以很方便地与单片机通用IO相连,进行串行总线读写传输。
显示模块选择16x2的字符点阵模块LCD 16020LC D 1602的控制器以Hitachi公司生产的HD44780芯片最为常见。
LC D 1602引脚主要包括3类,第1类是电源。
第2类是8位数据I/0通道,用于读写LC D 1602。
第3类是3根控制线,RS,R/W和E,其中,RS和R/W是用于实现LCD不同操作的。
E是作为读写的启动信号,有点类似一个时钟信号,数据要写人LC D 1602或从LCD 1602读出数据均需要首先置E信号为高至少1 s,然后置低。
调整时钟模块设计了4个轻触开关,用于设定和修改时间项。
数字万年历课程设计报告
数字万年历课程设计报告课程名称:微机原理课程设计题目:万年历摘要随着电子技术的迅速发展,特别是随大规模集成电路出现,给人类生活带来了根本性的改变。
由其是单片机技术的应用产品已经走进了千家万户。
电子万年历的出现给人们的生活带来的诸多方便。
本文首先描述系统硬件工作原理,并附以系统结构框图加以说明,着重介绍了本系统所应用的各硬件接口技术和各个接口模块的功能及工作过程,其次,详细阐述了程序的各个模块和实现过程。
本设计以数字集成电路技术为基础,单片机技术为核心。
本文编写的主导思想是软硬件相结合,以硬件为基础,来进行各功能模块的编写。
本设计是一种基于STC89C51单片机控制,DS1302报时的数字时钟设计。
它具有多项显示和控制功能。
能用LCD实时显示当前年、月、日、星期、时间;可对时间进行调整;具有调整时间和日期功能。
本设计通过一个基于单片机的能实现万年历功能电子时钟的设计,从而达到学习、了解单片机相关指令在各方面的应用。
系统由主控制器AT89C51、时钟电路DS1302、显示电路、按键电路和复位电路等部分构成,能实现时钟日历显示的功能,能进行时、分、秒的显示。
关键词:STC89C52单片机、LCD液晶显示、DS1302时钟芯片目录一、设计任务与要求 ........................................................................... - 6 -1.1 设计任务 .............................................................................................. - 6 -1.2 设计要求 .............................................................................................. - 6 -1.3 发挥部分 .............................................................................................. - 6 -二、方案总体设计 ..................................................................................... - 7 -2.1 显示部分 .............................................................................................. - 7 -2.2 时钟信号的选择 .................................................................................. - 8 -2.3 总体方案 .............................................................................................. - 8 -三、硬件设计 ..................................................................................... - 10 -3.1 单片机最小系统 ................................................................................ - 10 -3.2 DS1302时钟电路............................................................................... - 17 -3.3 LCD液晶显示模块............................................................................ - 19 -3.4 按键电路 ............................................................................................ - 21 -3.5 电源指示灯部分 ................................................................................ - 25 -四、软件设计 ..................................................................................... - 26 -4.1 主程序流程图显示 ............................................................................ - 26 -4.2 时间设定程序流程图 ........................................................................ - 27 -五、系统仿真与调试 ......................................................................... - 29 -5.1 Proteus仿真软件简介 ....................................................................... - 29 -5.2 仿真及实物 ........................................................................................ - 31 -六、设计总结 ..................................................................................... - 34 -七、参考文献 ..................................................................................... - 35 -一、设计任务与要求1.1 设计任务基于52单片机的DS1302万年历;1.2 设计要求基于52单片机,利用DS1302时钟芯片生成万年历,使用液晶显示年月日时分秒,显示值可通过按键修改。
制作电子万年历实训报告
一、引言随着科技的飞速发展,电子产品的普及和应用越来越广泛。
电子万年历作为一种常见的电子设备,不仅可以显示年、月、日、星期、时、分等信息,还可以实现闹钟、定时显示等功能。
为了提高我们的实践能力和创新能力,本次实训我们选择制作一款基于单片机的电子万年历。
二、实训目的1. 掌握电子万年历的基本原理和设计方法。
2. 熟悉单片机的编程和应用。
3. 培养团队协作能力和动手实践能力。
三、实训内容1. 硬件设计本实训所使用的硬件主要包括以下部分:- 单片机:AT89C52- 时钟模块:DS1302- 显示模块:LCD1602- 遥控模块:1838V- 按键模块:S1(设置键)、S2(上调键)、S3(下调键)、S4(复位键)硬件电路图如下:![电子万年历电路图](https:///5Q6zQ8Q.png)2. 软件设计本实训所使用的软件主要包括以下部分:- 单片机编程:C语言- 显示程序:LCD1602驱动程序- 遥控程序:1838V遥控接收程序软件流程图如下:![电子万年历软件流程图](https:///0Q7y8yJ.png)3. 功能实现本实训所实现的电子万年历具有以下功能:- 显示年、月、日、星期、时、分等信息。
- 遥控操作:设置时间、星期、日期等。
- 定时显示:定时显示当前时间。
- 停电自动计时:采用DS1302时钟模块,停电后可继续计时。
四、实训过程1. 硬件搭建首先,我们根据电路图搭建了电子万年历的硬件电路。
在搭建过程中,我们注意了以下几点:- 确保电路连接正确,避免短路或开路。
- 选择合适的元器件,确保电路性能稳定。
- 对电路进行测试,确保电路正常工作。
2. 软件编程接下来,我们使用C语言对单片机进行编程。
在编程过程中,我们遵循以下步骤:- 分析功能需求,确定程序结构。
- 编写程序代码,实现各项功能。
- 调试程序,确保程序运行正常。
3. 测试与优化在完成软件编程后,我们对电子万年历进行测试。
在测试过程中,我们发现以下问题:- 遥控操作不稳定。
用DS1302与LCD1602设计可调数字万年历课程设计
数字开发与实践课程设计题目:用DS1302与LCD1602设计可调式电子日历时钟班级:姓名:学号:学院:年月日用DS1302与LCD1602设计的可调式电子日历时钟一、总体设计1.1、设计目的为巩固所学的单片机知识,把所学理论运用到实践中,用LCD1602与DS1302 设计可调式电子日历时钟。
1.2、设计要求(1)显示:年、月、日、时、分、秒和星期;(2)设置年、月、日、时、分、秒和星期的初始状态;(3)能够用4个按键调整日历时钟的年、月、日、时、分、秒和星期;完成可调式电子日历时钟的硬件和软件的设计,包括单片机的相关内容;日历时钟模块的设计,液晶显示模块的设计,按键模块的设计。
控制程序的编写等。
备注:本程序另外添加了每到上午8:10和下午2:10的闹钟提醒功能。
1.3、系统基本方案选择和论证1.3.1、单片机芯片的选择方案方案一:采用89C51芯片作为硬件核心,采用Flash ROM,内部具有4KB ROM 存储空间,能于3V的超低压工作,而且与MCS-51系列单片机完全兼容。
方案二:采用STC12C5A60S2系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,是高速/低功耗/超强抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8-12倍。
内部集成MAX810专用复位电路,2路PWM,8路高速10位A/D转换(250K/S),针对电机控制,强干扰场合。
但造价较高。
1.3.2 、显示模块选择方案和论证:方案一:采用点阵式数码管显示,点阵式数码管是由八行八列的发光二极管组成,对于显示文字比较适合,如采用显示数字显得太浪费,且价格也相对较高。
所以不用此种作为显示。
方案二:采用LED数码管动态扫描,虽然LED数码管价格适中,但要显示多个数字所需要的个数偏多,功耗较大,显示出来的只是拼音,而不是汉字。
所以也不用此种作为显示。
方案三:采用LCD液晶显示屏,液晶显示屏的显示功能强大,可显示大量字符,且视觉效果较好,外形美观。
DS1302+LCD1602时钟
DS1302+LCD1602时钟1.实验目的效果:做一个不怕掉电的LCD显示时钟。
学习DS1302时钟芯片的读写,加强字符型液晶LCD1602的应用。
在LCD屏上显示格式:1)按一下SW1进入时间调整,关标会闪烁2)按一下SW2光标会在年份上闪烁,表明可以对年份进行调整,接着按SW3年份将加一,按SW4年份将减一;2)再按一下SW2,光标闪烁移到月份上,同样按SW3月份加一,按SW4月份减一;3)再按一下SW2,光标有下移到星期上,同样按SW3星期加一,按SW4星期减一;4)同样的道理可以调整时,分,秒。
5)调整完毕按一下SW1,光标闪烁退出,时间调整结束。
DS1302:1)读写时序:2)DS1302相关寄存器:(详细DS1302资料请查看ds1302.pdf文档)2.原理图:DS1302连接原理图LCD1602连接原理图3.实验板上操作:1)用三个短路冒将SCLK-P3.5,I/O-P3.6,CE-P3.7短接起来。
2)将板上的相应拨码开关拨到拨到ON上。
(建议把原来做过数码管显示的那个拨码开关全部拨到OFF那边)3)把LCD1602液晶插到实验板上的LCD1602液晶插槽上。
(提示:程序烧进单片机后,液晶上没有显示,请调节板子上左上角那个电位器)4)按一下SW1进入时间调整,关标会闪烁按一下SW2光标会在年份上闪烁,表明可以对年份进行调整,接着按SW3年份将加一,按SW4年份将减一;再按一下SW2,光标闪烁移到月份上,同样按SW3月份加一,按SW4月份减一;再按一下SW2,光标有下移到星期上,同样按SW3星期加一,按SW4星期减一;同样的道理可以调整时,分,秒。
调整完毕按一下SW1,光标闪烁退出,时间调整结束。
4.实物连接图如下:5.C语言程序:#include "A T89X51.h"#include "intrins.h"#define HIGH 1#define LOW 0#define TRUE 1#define ZERO 0#define MSB 0x80#define LSB 0x01// ds1302 PreDefinition#define DS1302_WP0x8E#define DS1302_RESET RST=LOW;SCL=LOW;RST=HIGH#define DS1302_WP_ENABLE Write_Ds1302(DS1302_WP,0X00)#define DS1302_WP_DISENABLE Write_Ds1302(DS1302_WP,0x00) #define LCDPORT P0sbit SCL = P3^5;// DS1302 Serial-Clock Input pin 5sbit SDA = P3^6;// DS1302 Serial-Data Input pin 6sbit RST = P3^7;// DS1302 Chip-Seclet Input pin 7sbit RS=P1^0;sbit RW=P1^1;sbit EN=P1^2;code unsigned char set_rtc_code[7]={0x07,0x03,0x29,0x02,0x21,0x07,0x40};code unsigned char write_rtc_address[7]={0x8c,0x88,0x86,0x8a,0x84,0x82,0x80};code unsigned char read_rtc_address[7]={0x8d,0x89,0x87,0x8b,0x85,0x83,0x81}; unsigned char read_rtc_code[7]; //DS1302读出信息(年份,星期,时间)暂存数组,/********1ms延时子程序***********/delay_nms(unsigned int n){unsigned int i;unsigned char j;for(i=0;i<n;i++)for(j=0;j<120;j++); //空操作}//*************LCD1602驱动程序***************************//void lcd_delay(unsigned char delaytime){while(delaytime)delaytime--;}void write_lcd_command(unsigned char write_command){lcd_delay(40);RS=0;RW=0;LCDPORT=write_command;EN=1;EN=0;}void write_lcd_data(unsigned char write_data){lcd_delay(40);RS=1;RW=0;LCDPORT=write_data;EN=1;EN=0;}void LCD_write_char( unsigned x,unsigned char y,unsigned char dat) //x表示行,y表示该行的位置(也就是列){//LCD_set_xy( x, y );switch(x){case 0:write_lcd_command(0x80+y);break;case 1:write_lcd_command(0xc0+y);break;}// LCD_en_dat(dat);write_lcd_data(dat|0x30); //dat或上0x30,就时把数字0123456789转换成ASIIC码}void lcd_displaystr(unsigned char x,unsigned char y,unsigned char code *str){switch(x){case 0:write_lcd_command(0x80+y);break;case 1:write_lcd_command(0xc0+y);break;}while (*str){write_lcd_data(*str);str++;}}void initial_lcd1602(void) //初始化LCD1602{unsigned char i;EN=0;for(i=200;i>0;i--)lcd_delay(248);write_lcd_command(0x38);for(i=4;i>0;i--)lcd_delay(248);write_lcd_command(0x38);for(i=4;i>0;i--)lcd_delay(248);write_lcd_command(0x0f);for(i=4;i>0;i--)lcd_delay(248);write_lcd_command(0x06);for(i=4;i>0;i--)lcd_delay(248);write_lcd_command(0x01);for(i=4;i>0;i--)lcd_delay(248);}//********************lcd1602驱动程序到此完********************/////////////////////////////////////////////////////////////////////////**************ds1302读写程序*************************//void Write_Ds1302_Byte(unsigned char temp) //写一个字节{unsigned char i;for (i=0;i<8;i++){SCL=LOW;SDA=temp&LSB;temp>>=1;SCL=HIGH;}}/****************************************************************************/ void Write_Ds1302( unsigned char address,unsigned char dat ) //写ds1302{DS1302_RESET;Write_Ds1302_Byte(address);Write_Ds1302_Byte(dat);RST=LOW;}/****************************************************************************/ unsigned char Read_Ds1302 ( unsigned char address ) //读ds1302{unsigned char i,temp=0x00,temp_temp;DS1302_RESET;Write_Ds1302_Byte(address);for (i=0;i<8;i++){if(SDA)temp|=0x80;SCL=LOW;temp>>=1;SCL=HIGH;}RST=LOW;temp_temp=temp/16;temp=temp%16;temp=temp+temp_temp*10;return (temp);}/****************************************************************************/ void Read_RTC(void) //读出DS1302里的相关信息,存放在read_rtd_code[]数组中{unsigned char i,*p;p=read_rtc_address;for(i=0;i<7;i++){read_rtc_code[i]=Read_Ds1302(*p);p++;}}/***********************************************************************/void Set_RTC(void) //初始化设置DS1302{unsigned char i,*p;p=write_rtc_address;for(i=0;i<7;i++){Write_Ds1302(*p,set_rtc_code[i]);p++;}}/******************************************************/void initial_ds1302(void) //初始化ds1302{DS1302_WP_ENABLE;Set_RTC();}/**************ds1302读写程序到此完************************//////////////////////////////////////////////////////系统初始化void system_initial(void){initial_ds1302();initial_lcd1602();}/****************************************************************************/void main(void){unsigned char count,staus;system_initial();//输出显示lcd_displaystr(0,0x00,"20");delay_nms(10);lcd_displaystr(0,0x04,"-");delay_nms(10);lcd_displaystr(0,0x07,"-");lcd_displaystr(0,0x0b,"Week:");lcd_displaystr(1,0x00,"Time:");lcd_displaystr(1,0x07,":");lcd_displaystr(1,0x0a,":");while(1){//按键扫描,实现对时间的调整,对应实验板的独立按钮//开始时间设置,staus=1if(P2_0==0){delay_nms(10);if(P2_0==0){staus^=1;count=0;while(P2_0==0);}}if(P2_1==0){delay_nms(10);if(P2_1==0){count++; //光标移位if(count==8)count=1;while(P2_1==0);}}if(P2_2==0) //加按钮{delay_nms(10);if(P2_2==0){switch(count){case 0x01:read_rtc_code[0]++;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[0],(read_rtc_code[0]+(read_rtc_code[0]/10)*6));LCD_write_char(0,0x02,(read_rtc_code[0]/10)); //年十位LCD_write_char(0,0x03,(read_rtc_code[0]%10)); //年个位break;case 0x02:read_rtc_code[1]++;if(read_rtc_code[1]==13)read_rtc_code[1]=1;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[1],(read_rtc_code[1]+(read_rtc_code[1]/10)*6));LCD_write_char(0,0x05,(read_rtc_code[1]/10)); //月十位LCD_write_char(0,0x06,(read_rtc_code[1]%10)); //月个位break;case 0x03:read_rtc_code[2]++;if(read_rtc_code[2]==31)read_rtc_code[2]=1;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[2],(read_rtc_code[2]+(read_rtc_code[2]/10)*6));LCD_write_char(0,0x08,(read_rtc_code[2]/10)); //日十位LCD_write_char(0,0x09,(read_rtc_code[2]%10)); //日个位break;case 0x04:read_rtc_code[3]++;if(read_rtc_code[3]==8)read_rtc_code[3]=1;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[3],(read_rtc_code[3]+(read_rtc_code[3]/10)*6));LCD_write_char(0,0x0f,(read_rtc_code[3]%10)); //星期break;case 0x05:read_rtc_code[4]++;if(read_rtc_code[4]==25)read_rtc_code[4]=0;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[4],(read_rtc_code[4]+(read_rtc_code[4]/10)*6));LCD_write_char(1,0x05,(read_rtc_code[4]/10)); //时十位LCD_write_char(1,0x06,(read_rtc_code[4]%10)); //时个位break;case 0x06:read_rtc_code[5]++;if(read_rtc_code[5]==60)read_rtc_code[5]=0;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[5],(read_rtc_code[5]+(read_rtc_code[5]/10)*6));LCD_write_char(1,0x08,(read_rtc_code[5]/10)); //分十位LCD_write_char(1,0x09,(read_rtc_code[5]%10)); //分个位break;case 0x07:read_rtc_code[6]++;if(read_rtc_code[6]==60)read_rtc_code[6]=0;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[6],(read_rtc_code[6]+(read_rtc_code[6]/10)*6));LCD_write_char(1,0x0b,(read_rtc_code[6]/10)); //秒十位LCD_write_char(1,0x0c,(read_rtc_code[6]%10)); //秒个位break;default:break;}while(P2_2==0);}}if(P2_3==0) //减按钮{delay_nms(10);if(P2_3==0){switch(count){case 0x01:if(read_rtc_code[0]==0){lcd_displaystr(0,0x00,"19");read_rtc_code[0]=99;}elseread_rtc_code[0]--;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[0],(read_rtc_code[0]+(read_rtc_code[0]/10)*6));LCD_write_char(0,0x02,(read_rtc_code[0]/10)); //年十位LCD_write_char(0,0x03,(read_rtc_code[0]%10)); //年个位break;case 0x02:if(read_rtc_code[1]==1)read_rtc_code[1]=12;elseread_rtc_code[1]--;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[1],(read_rtc_code[1]+(read_rtc_code[1]/10)*6));LCD_write_char(0,0x05,(read_rtc_code[1]/10)); //月十位LCD_write_char(0,0x06,(read_rtc_code[1]%10)); //月个位break;case 0x03:if(read_rtc_code[2]==1)read_rtc_code[2]=30;elseread_rtc_code[2]--;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[2],(read_rtc_code[2]+(read_rtc_code[2]/10)*6));LCD_write_char(0,0x08,(read_rtc_code[2]/10)); //日十位LCD_write_char(0,0x09,(read_rtc_code[2]%10)); //日个位break;case 0x04:if(read_rtc_code[3]==1)read_rtc_code[3]=7;elseread_rtc_code[3]--;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[3],(read_rtc_code[3]+(read_rtc_code[3]/10)*6));LCD_write_char(0,0x0f,(read_rtc_code[3]%10)); //星期break;case 0x05:if(read_rtc_code[4]==0)read_rtc_code[4]=24;elseread_rtc_code[4]--;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[4],(read_rtc_code[4]+(read_rtc_code[4]/10)*6));LCD_write_char(1,0x05,(read_rtc_code[4]/10)); //时十位LCD_write_char(1,0x06,(read_rtc_code[4]%10)); //时个位break;case 0x06:if(read_rtc_code[5]==00)read_rtc_code[5]=59;elseread_rtc_code[5]--;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[5],(read_rtc_code[5]+(read_rtc_code[5]/10)*6));LCD_write_char(1,0x08,(read_rtc_code[5]/10)); //分十位LCD_write_char(1,0x09,(read_rtc_code[5]%10)); //分个位break;case 0x07:if(read_rtc_code[6]==0)read_rtc_code[6]=59;elseread_rtc_code[6]--;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[6],(read_rtc_code[6]+(read_rtc_code[6]/10)*6));LCD_write_char(1,0x0b,(read_rtc_code[6]/10)); //秒十位LCD_write_char(1,0x0c,(read_rtc_code[6]%10)); //秒个位break;default:break;}while(P2_3==0);}}if(staus==0){//读出DS1302寄存器里的时间信息RST=HIGH;Read_RTC();LCD_write_char(0,0x02,(read_rtc_code[0]/10)); //年十位LCD_write_char(0,0x03,(read_rtc_code[0]%10)); //年个位LCD_write_char(0,0x05,(read_rtc_code[1]/10)); //月十位LCD_write_char(0,0x06,(read_rtc_code[1]%10)); //月个位LCD_write_char(0,0x08,(read_rtc_code[2]/10)); //日十位LCD_write_char(0,0x09,(read_rtc_code[2]%10)); //日个位LCD_write_char(0,0x0f,(read_rtc_code[3]%10)); //星期LCD_write_char(1,0x05,(read_rtc_code[4]/10)); //时十位LCD_write_char(1,0x06,(read_rtc_code[4]%10)); //时个位LCD_write_char(1,0x08,(read_rtc_code[5]/10)); //分十位LCD_write_char(1,0x09,(read_rtc_code[5]%10)); //分个位LCD_write_char(1,0x0b,(read_rtc_code[6]/10)); //秒十位LCD_write_char(1,0x0c,(read_rtc_code[6]%10)); //秒个位}else{RST=LOW;switch(count){case 0x01:write_lcd_command(0x83);break;case 0x02:write_lcd_command(0x86);break;case 0x03:write_lcd_command(0x89);break;case 0x04:write_lcd_command(0x8f);break;case 0x05:write_lcd_command(0xc6);break;case 0x06:write_lcd_command(0xc9);break;case 0x07:write_lcd_command(0xcc);break;default:break;}}}}。
基于利用时钟芯片DS1302实现万年历,1602LCD显示电子表
基于利用时钟芯片DS1302实现万年历,1602LCD显示电子表电子设计大赛培训第二时期第**组报告《基于利用时钟芯片DS1302实现万年历,1602LCD显示电子表》成员姓名:*** 学号:******成员姓名:HG** 学号:******成员姓名:*** 学号:*******一、要紧功能1、在1602液晶上显示年、月、日、星期、时、分、秒以及实时温度,同时实时更新显示;2、通过按键随时调剂各显示参数,分别实现光标定位、数值增大、数值减小、闹钟和温度上下限查看的功能;3.在时刻显现乱码的情形下,具有一键初始化时刻的功能。
二、电路图三、实物图1.开关模块2、显示模块3、at89c52模块4、总体连接图四、心得体会本次设计是我们遇到过的较大的设计,因此遇到的问题也比较的多,专门是往常没有接触过如此复杂的硬件电路以及软件编程,在软、硬件设计和调试中遇到了许多的困难,在同学的关心才逐一克服了难题,学习到了许多的专业知识。
在整个设计过程之前,我差不多在网上找了相关方面的资料,万事开始难,一开始不明白从哪里下手。
后来慢慢学会分析系统,将系统模块化,各个模块能够在软件或者硬件上实现。
在确保各个模块的硬件电路和与之相搭配的程序能够正常工作后在把它们组成一个系统。
在今后的生活里,我会进一步加强自己的动手能力,丰富自己的知识面。
总之,这次设计给我的最大感触确实是,在以后的学习中勤动脑,多动手。
附录:1、元件清单AT89C52 一块LCD 一个排阻 3个DS1302 一个DS18B20 一个开关 5个晶振 2个瓷片电容 2个, 30PF电解电容一个, 33Uf插针若干杜邦线若干2、程序#include <REG51.H>#include <intrins.h>//#include "LCD1602.h"//#include "DS1302.h"#define uint unsigned int#define uchar unsigned charsbit DS1302_CLK = P1^7; //实时时钟时钟线引脚sbit DS1302_IO = P1^6; //实时时钟数据线引脚sbit DS1302_RST = P1^5; //实时时钟复位线引脚sbit wireless_1 = P3^0;sbit wireless_2 = P3^1;sbit wireless_3 = P3^2;sbit wireless_4 = P3^3;sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;charhide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,时到日,月,年位闪的计数sbit Set = P2^0; //模式切换键sbit Up = P2^1; //加法按钮sbit Down = P2^2; //减法按钮sbit out = P2^3; //赶忙跳出调整模式按钮sbit DQ = P1^0; //温度传送数据IO口char done,count,temp,flag,up_flag,down_flag;uchar temp_value; //温度值uchar TempBuffer[5],week_value[2];void show_time(); //液晶显示程序/***********1602液晶显示部分子程序****************///PortDefinitions********************************************************* *sbit LcdRs = P2^5;sbit LcdRw = P2^6;sbit LcdEn = P2^7;sfr DBPort = 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口//内部等待函数******************************************************************** ******unsigned char LCD_Wait(void){LcdRs=0;LcdRw=1; _nop_();LcdEn=1; _nop_();LcdEn=0;return DBPort;}//向LCD写入命令或数据************************************************************#define LCD_COMMAND 0 // Command#define LCD_DATA 1 // Data#define LCD_CLEAR_SCREEN 0x01 // 清屏#define LCD_HOMING 0x02 // 光标返回原点void LCD_Write(bit style, unsigned char input){LcdEn=0;LcdRs=style;LcdRw=0; _nop_();DBPort=input; _nop_();//注意顺序LcdEn=1; _nop_();//注意顺序LcdEn=0; _nop_();LCD_Wait();}//设置显示模式************************************************************#define LCD_SHOW 0x04 //显示开#define LCD_HIDE 0x00 //显示关#define LCD_CURSOR 0x02 //显示光标#define LCD_NO_CURSOR 0x00 //无光标#define LCD_FLASH 0x01 //光标闪动#define LCD_NO_FLASH 0x00 //光标不闪动void LCD_SetDisplay(unsigned char DisplayMode){LCD_Write(LCD_COMMAND, 0x08|DisplayMode);}//设置输入模式************************************************************#define LCD_AC_UP 0x02#define LCD_AC_DOWN 0x00 // default#define LCD_MOVE 0x01 // 画面可平移#define LCD_NO_MOVE 0x00 //defaultvoid LCD_SetInput(unsigned char InputMode){LCD_Write(LCD_COMMAND, 0x04|InputMode);}//初始化LCD************************************************************void LCD_Initial(){LcdEn=0;LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵LCD_Write(LCD_COMMAND,0x38);LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动}//液晶字符输入的位置************************void GotoXY(unsigned char x, unsigned char y){if(y==0)LCD_Write(LCD_COMMAND,0x80|x);if(y==1)LCD_Write(LCD_COMMAND,0x80|(x-0x40));}//将字符输出到液晶显示void Print(unsigned char *str){while(*str!='\0'){LCD_Write(LCD_DATA,*str);str++;}}/***********DS1302时钟部分子程序******************/typedef struct __SYSTEMTIME__{unsigned char Second;unsigned char Minute;unsigned char Hour;unsigned char Week;unsigned char Day;unsigned char Month;unsigned char Year;unsigned char DateString[11];unsigned char TimeString[9];}SYSTEMTIME; //定义的时刻类型SYSTEMTIME CurrentTime;#define AM(X) X#define PM(X) (X+12) // 转成24小时制#define DS1302_SECOND 0x80 //时钟芯片的寄存器位置,存放时刻#define DS1302_MINUTE 0x82#define DS1302_HOUR 0x84#define DS1302_WEEK 0x8A#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8Cvoid DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数) {unsigned char i;ACC = d;for(i=8; i>0; i--){DS1302_IO = ACC0; //相当于汇编中的 RRCDS1302_CLK = 1;DS1302_CLK = 0;ACC = ACC >> 1;}}unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数) {unsigned char i;for(i=8; i>0; i--){ACC = ACC >>1; //相当于汇编中的 RRCACC7 = DS1302_IO;DS1302_CLK = 1;DS1302_CLK = 0;}return(ACC);}void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据{DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr); // 地址,命令DS1302InputByte(ucDa); // 写1Byte数据DS1302_CLK = 1;DS1302_RST = 0;}unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据{unsigned char ucData;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr|0x01); // 地址,命令ucData = DS1302OutputByte(); // 读1Byte数据DS1302_CLK = 1;DS1302_RST = 0;return(ucData);}void DS1302_GetTime(SYSTEMTIME *Time) //猎取时钟芯片的时钟数据到自定义的结构型数组{unsigned char ReadValue;ReadValue = Read1302(DS1302_SECOND);Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_MINUTE);Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_HOUR);Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_DAY);Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_WEEK);Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_MONTH);Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_YEAR);Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);}void DateToStr(SYSTEMTIME *Time) //将时刻年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]{ if(hide_year<2) //那个地点的if,else语句差不多上判定位闪耀,<2显示数据,>2就不显示,输出字符串为 2007/07/22{Time->DateString[0] = '2';Time->DateString[1] = '0';Time->DateString[2] = Time->Year/10 + '0';Time->DateString[3] = Time->Year%10 + '0';}else{Time->DateString[0] = ' ';Time->DateString[1] = ' ';Time->DateString[2] = ' ';Time->DateString[3] = ' ';}Time->DateString[4] = '/';if(hide_month<2){Time->DateString[5] = Time->Month/10 + '0';Time->DateString[6] = Time->Month%10 + '0';}else{Time->DateString[5] = ' ';Time->DateString[6] = ' ';}Time->DateString[7] = '/';if(hide_day<2){Time->DateString[8] = Time->Day/10 + '0';Time->DateString[9] = Time->Day%10 + '0';}else{Time->DateString[8] = ' ';Time->DateString[9] = ' ';}if(hide_week<2){week_value[0] = Time->Week%10 + '0'; //星期的数据另外放到week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示}else{week_value[0] = ' ';}week_value[1] = '\0';Time->DateString[10] = '\0'; //字符串末尾加 '\0' ,判定终止字符}void TimeToStr(SYSTEMTIME *Time) //将时,分,秒数据转换成液晶显示字符放到数组 TimeString[];{ if(hide_hour<2){Time->TimeString[0] = Time->Hour/10 + '0';Time->TimeString[1] = Time->Hour%10 + '0';}else{Time->TimeString[0] = ' ';Time->TimeString[1] = ' ';}Time->TimeString[2] = ':';if(hide_min<2){Time->TimeString[3] = Time->Minute/10 + '0';Time->TimeString[4] = Time->Minute%10 + '0';}else{Time->TimeString[3] = ' ';Time->TimeString[4] = ' ';}Time->TimeString[5] = ':';if(hide_sec<2){Time->TimeString[6] = Time->Second/10 + '0';Time->TimeString[7] = Time->Second%10 + '0';}else{Time->TimeString[6] = ' ';Time->TimeString[7] = ' ';}Time->DateString[8] = '\0';}void Initial_DS1302(void) //时钟芯片初始化{unsigned char Second=Read1302(DS1302_SECOND);if(Second&0x80) //判定时钟芯片是否关闭{Write1302(0x8e,0x00); //写入承诺Write1302(0x8c,0x07); //以下写入初始化时刻日期:07/07/25.星期: 3. 时刻: 23:59:55Write1302(0x88,0x07);Write1302(0x86,0x25);Write1302(0x8a,0x07);Write1302(0x84,0x23);Write1302(0x82,0x59);Write1302(0x80,0x55);Write1302(0x8e,0x80); //禁止写入}}/***********ds18b20子程序*************************//***********ds18b20延迟子函数(晶振12MHz )*******/void delay_18B20(unsigned int i){while(i--);}/**********ds18b20初始化函数**********************/void Init_DS18B20(void){unsigned char x=0;DQ = 1; //DQ复位delay_18B20(8); //稍做延时DQ = 0; //单片机将DQ拉低delay_18B20(80); //精确延时大于 480usDQ = 1; //拉高总线delay_18B20(14);x=DQ; //稍做延时后假如x=0则初始化成功 x=1则初始化失败delay_18B20(20);}/***********ds18b20读一个字节**************/unsigned char ReadOneChar(void){uchar i=0;uchar dat = 0;for (i=8;i>0;i--){DQ = 0; // 给脉冲信号dat>>=1;DQ = 1; // 给脉冲信号if(DQ)dat|=0x80;delay_18B20(4);}return(dat);}/*************ds18b20写一个字节****************/void WriteOneChar(uchar dat){unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = dat&0x01;delay_18B20(5);DQ = 1;dat>>=1;}}/**************读取ds18b20当前温度************/void ReadTemp(void){unsigned char a=0;unsigned char b=0;unsigned char t=0;Init_DS18B20();WriteOneChar(0xCC); // 跃过读序号列号的操作WriteOneChar(0x44); // 启动温度转换delay_18B20(100); // this message is wery importantInit_DS18B20();WriteOneChar(0xCC); //跃过读序号列号的操作WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器)前两个确实是温度delay_18B20(100);a=ReadOneChar(); //读取温度值低位b=ReadOneChar(); //读取温度值高位temp_value=b<<4;temp_value+=(a&0xf0)>>4;}void temp_to_str() //温度数据转换成液晶字符显示{TempBuffer[0]=temp_value/10+'0'; //十位TempBuffer[1]=temp_value%10+'0'; //个位TempBuffer[2]=0xdf; //温度符号TempBuffer[3]='C';TempBuffer[4]='\0';}void Delay1ms(unsigned int count){unsigned int i,j;for(i=0;i<count;i++)for(j=0;j<120;j++);}/*延时子程序*/void mdelay(uint delay){ uint i;for(;delay>0;delay--){for(i=0;i<62;i++) //1ms延时.{;}}}void outkey() //跳出调整模式,返回默认显示{ uchar Second;if(out==0||wireless_1==1){ mdelay(8);count=0;hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_mon th=0,hide_year=0;Second=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入承诺Write1302(0x80,Second&0x7f);Write1302(0x8E,0x80); //禁止写入done=0;while(out==0);while(wireless_1==1);}}//////////////////////////////////////////////////////////////////// ////////////////////////////////////////void Upkey()//升序按键{Up=1;if(Up==0||wireless_2==1){mdelay(8);switch(count){case 1:temp=Read1302(DS1302_SECOND); //读取秒数temp=temp+1; //秒数加1up_flag=1; //数据调整后更新标志if((temp&0x7f)>0x59) //超过59秒,清零temp=0;break;case 2:temp=Read1302(DS1302_MINUTE); //读取分数temp=temp+1; //分数加1up_flag=1;if(temp>0x59) //超过59分,清零temp=0;break;case 3:temp=Read1302(DS1302_HOUR); //读取小时数temp=temp+1; //小时数加1up_flag=1;if(temp>0x23) //超过23小时,清零temp=0;break;case 4:temp=Read1302(DS1302_WEEK); //读取星期数temp=temp+1; //星期数加1up_flag=1;if(temp>0x7)temp=1;break;case 5:temp=Read1302(DS1302_DAY); //读取日数temp=temp+1; //日数加1up_flag=1;if(temp>0x31)temp=1;break;case 6:temp=Read1302(DS1302_MONTH); //读取月数temp=temp+1; //月数加1up_flag=1;if(temp>0x12)temp=1;break;case 7:temp=Read1302(DS1302_YEAR); //读取年数temp=temp+1; //年数加1up_flag=1;if(temp>0x85)temp=0;break;default:break;}while(Up==0);while(wireless_2==1);}}//////////////////////////////////////////////////////////////////// ////////////////////////////////////////void Downkey()//降序按键{Down=1;if(Down==0||wireless_3==1){mdelay(8);switch(count){case 1:temp=Read1302(DS1302_SECOND); //读取秒数temp=temp-1; //秒数减1down_flag=1; //数据调整后更新标志if(temp==0x7f) //小于0秒,返回59秒temp=0x59;break;case 2:temp=Read1302(DS1302_MINUTE); //读取分数temp=temp-1; //分数减1down_flag=1;if(temp==-1)temp=0x59; //小于0秒,返回59秒break;case 3:temp=Read1302(DS1302_HOUR); //读取小时数temp=temp-1; //小时数减1down_flag=1;if(temp==-1)temp=0x23;break;case 4:temp=Read1302(DS1302_WEEK); //读取星期数temp=temp-1; //星期数减1down_flag=1;if(temp==0)temp=0x7;;break;case 5:temp=Read1302(DS1302_DAY); //读取日数temp=temp-1; //日数减1down_flag=1;if(temp==0)temp=31;break;case 6:temp=Read1302(DS1302_MONTH); //读取月数temp=temp-1; //月数减1down_flag=1;if(temp==0)temp=12;break;case 7:temp=Read1302(DS1302_YEAR); //读取年数temp=temp-1; //年数减1down_flag=1;if(temp==-1)temp=0x85;break;default:break;}while(Down==0);while(wireless_3==1);}}void Setkey()//模式选择按键{Set=1;if(Set==0||wireless_4==1){mdelay(8);count=count+1; //Setkey按一次,count就加1done=1; //进入调整模式while(Set==0);while(wireless_4==1);}}void keydone()//按键功能执行{ uchar Second;if(flag==0) //关闭时钟,停止计时{ Write1302(0x8e,0x00); //写入承诺temp=Read1302(0x80);Write1302(0x80,temp|0x80);Write1302(0x8e,0x80); //禁止写入flag=1;}Setkey(); //扫描模式切换按键 switch(count){case 1:do //count=1,调整秒{outkey(); //扫描跳出按钮Upkey(); //扫描加按钮Downkey(); //扫描减按钮if(up_flag==1||down_flag==1) //数据更新,重新写入新的数据{Write1302(0x8e,0x00); //写入承诺Write1302(0x80,temp|0x80); //写入新的秒数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_sec++; //位闪计数if(hide_sec>3)hide_sec=0;show_time(); //液晶显示数据}while(count==2);break;case 2:do //count=2,调整分{hide_sec=0;outkey();Upkey();Downkey();if(temp>0x60)temp=0;if(up_flag==1||down_flag==1)Write1302(0x8e,0x00); //写入承诺Write1302(0x82,temp); //写入新的分数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_min++;if(hide_min>3)hide_min=0;show_time();}while(count==3);break;case 3:do //count=3,调整小时{hide_min=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入承诺Write1302(0x84,temp); //写入新的小时数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_hour++;if(hide_hour>3)hide_hour=0;show_time();}while(count==4);break;case 4:do //count=4,调整星期{hide_hour=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入承诺Write1302(0x8a,temp); //写入新的星期数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;hide_week++;if(hide_week>3)hide_week=0;show_time();}while(count==5);break;case 5:do //count=5,调整日{hide_week=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入承诺Write1302(0x86,temp); //写入新的日数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_day++;if(hide_day>3)hide_day=0;show_time();}while(count==6);break;case 6:do //count=6,调整月{hide_day=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入承诺Write1302(0x88,temp); //写入新的月数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_month++;if(hide_month>3)hide_month=0;show_time();}while(count==7);break;case 7:do //count=7,调整年{hide_month=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入承诺Write1302(0x8c,temp); //写入新的年数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_year++;if(hide_year>3)hide_year=0;show_time();}while(count==8);break;case 8: count=0;hide_year=0; //count8, 跳出调整模式,返回默认显示状态Second=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入承诺Write1302(0x80,Second&0x7f);Write1302(0x8E,0x80); //禁止写入done=0;break; //count=7,开启中断,标志位置0并退出default:break;}}void show_time() //液晶显示程序{DS1302_GetTime(&CurrentTime); //猎取时钟芯片的时刻数据TimeToStr(&CurrentTime); //时刻数据转换液晶字符DateToStr(&CurrentTime); //日期数据转换液晶字符ReadTemp(); //开启温度采集程序temp_to_str(); //温度数据转换成液晶字符GotoXY(12,1); //液晶字符显示位置Print(TempBuffer); //显示温度GotoXY(0,1);Print(CurrentTime.TimeString); //显示时刻GotoXY(0,0);Print(CurrentTime.DateString); //显示日期GotoXY(15,0);Print(week_value); //显示星期GotoXY(11,0);Print("Week"); //在液晶上显示字母 weekDelay1ms(400); //扫描延时}main(){flag=1; //时钟停止标志LCD_Initial(); //液晶初始化Init_DS18B20( ) ; //DS18B20初始化Initial_DS1302(); //时钟芯片初始化up_flag=0;down_flag=0;done=0; //进入默认液晶显示wireless_1=0;wireless_2=0;wireless_3=0;wireless_4=0;while(1){while(done==1)keydone(); //进入调整模式while(done==0){show_time(); //液晶显示数据 flag=0;Setkey(); //扫描各功能键}}}。
ATmega16、DS1302、LCD1602组成的可设置万年历电子表
ATmega16、DS1302、LCD1602组成的可设置万年历电子表一、简要说明我看了很多人做这个经典的项目,不少人在网上到处求索资料,找人解答疑问。
奈何现在很多的网站,动不动就要你注册,很多的解答也只有只言片语。
我就把这个项目直接做出来,所有的都公布在网上的,希望对新手有所帮助。
这其中有个小知识点,我这边有一段程序可以用年月日信息来计算星期。
具体是怎么样的个原理就不多说了,直接把代码贴在了本文的第三部分,有需要的可以直接拿去。
虽然DS1302带有星期功能,但是本身的星期功能在设置日期的时候不能自动跟随着变化,故不建议使用。
关于DS1302使用的石英晶振,标称频率为32.768kHz,无需任何外接电阻或电容,许多地方说要接外部电容,这是错误的。
DS1302归根结底有以下几种操作:1.初始化操作:DS1302可以通过工作电源(VCC2)对后备电源(VCC1)进行充电,初始化的时候需要指定导通二极管的个数、限流电阻的规格。
一般来说在初始化完成后,就可以直接打开DS1302。
2.读取内存数据:0XC1~0XFD,可以当做掉电保持寄存器使用,每个寄存器间隔1个地址读。
3.写入内存数据:0XC0~0XFC,可以当做掉电保持寄存器使用,每个寄存器间隔1个地址写。
4.设置日期:设置年月日1/ 85.设置时间:设置时分秒6.读取日期:读取年月日7.读取时间:读取时分秒程序思路简要说明,上电对进入初始化阶段、首先是MCU初始化、关闭总中断开关。
再对DS1302作初始化,并启用它。
然后对LM1602作初始化。
随后程序进入主循环。
主循环内有个模式控制函数,分为0~6共计七种模式。
模式0为正常显示模式,1~6分别对应年、月、日、时、分、秒设置模式。
进入对应的设置模式时,相关显示在LCD上出现闪烁。
按下M键可以依次在0~7模式之间循环切换。
本项目中,还设计有分钟脉冲对时操作,在某些场合下,本装置可接收卫星时钟装置发送的分钟脉冲对时信号。
基于利用时钟芯片DS1302实现万年历,1602LCD显示电子表
电子设计大赛培训第二阶段第**组报告《基于利用时钟芯片DS1302实现万年历,1602LCD显示电子表》成员姓名:*** 学号:******成员姓名:HG**学号:******成员姓名:*** 学号:*******一、主要功能1、在1602液晶上显示年、月、日、星期、时、分、秒以及实时温度,并且实时更新显示;2、通过按键随时调节各显示参数,分别实现光标定位、数值增大、数值减小、闹钟和温度上下限查看的功能;3.在时间出现乱码的情况下,具有一键初始化时间的功能。
二、电路图三、实物图1.开关模块2、显示模块3、at89c52模块4、总体连接图四、心得体会本次设计是我们遇到过的较大的设计,所以遇到的问题也比较的多,尤其是以前没有接触过如此复杂的硬件电路以及软件编程,在软、硬件设计和调试中遇到了不少的困难,在同学的帮助才逐一克服了难题,学习到了不少的专业知识。
在整个设计过程之前,我已经在网上找了相关方面的资料,万事开始难,一开始不知道从哪里下手。
后来慢慢学会分析系统,将系统模块化,各个模块可以在软件或者硬件上实现。
在确保各个模块的硬件电路和与之相搭配的程序能够正常工作后在把它们组成一个系统。
在今后的日子里,我会进一步加强自己的动手能力,丰富自己的知识面。
总之,这次设计给我的最大感触就是,在以后的学习中勤动脑,多动手。
附录:1、元件清单AT89C52一块LCD 一个排阻 3个DS1302一个DS18B20一个开关 5个晶振2个瓷片电容2个, 30PF电解电容一个,33Uf插针若干杜邦线若干2、程序#include <REG51.H>#include <intrins.h>//#include "LCD1602.h"//#include "DS1302.h"#define uint unsigned int#define uchar unsigned charsbit DS1302_CLK = P1^7; //实时时钟时钟线引脚sbit DS1302_IO = P1^6; //实时时钟数据线引脚sbit DS1302_RST=P1^5; //实时时钟复位线引脚sbitwireless_1 = P3^0;sbit wireless_2=P3^1;sbit wireless_3 = P3^2;sbit wireless_4 = P3^3;sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,时到日,月,年位闪的计数sbit Set = P2^0; //模式切换键sbit Up = P2^1; //加法按钮sbitDown = P2^2;//减法按钮sbit out = P2^3; //立刻跳出调整模式按钮sbit DQ =P1^0; //温度传送数据IO口char done,count,temp,flag,up_flag,down_flag;uchar temp_value;//温度值uchar TempBuffer[5],week_value[2];void show_time(); //液晶显示程序/***********1602液晶显示部分子程序****************///Port Definitions**********************************************************sbitLcdRsﻩ= P2^5;sbit LcdRwﻩ= P2^6;sbitLcdEn = P2^7;sfr DBPort = 0x80;ﻩ//P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口//内部等待函数**************************************************************************unsignedchar LCD_Wait(void){ﻩLcdRs=0;ﻩLcdRw=1;ﻩ_nop_();LcdEn=1; _nop_();ﻩﻩﻩﻩLcdEn=0;ﻩreturnDBPort;}//向LCD写入命令或数据************************************************************#define LCD_COMMAND ﻩﻩ0 // Command#define LCD_DATAﻩ 1 //Data#defineLCD_CLEAR_SCREEN 0x01 // 清屏#define LCD_HOMING ﻩ0x02// 光标返回原点void LCD_Write(bit style, unsigned char input){LcdEn=0;ﻩLcdRs=style;LcdRw=0; ﻩ_nop_();DBPort=input;ﻩ_nop_();//注意顺序LcdEn=1; ﻩ_nop_();//注意顺序ﻩLcdEn=0; ﻩ_nop_();ﻩLCD_Wait();}//设置显示模式************************************************************#define LCD_SHOW ﻩﻩ0x04 //显示开#defineLCD_HIDEﻩ0x00 //显示关#define LCD_CURSORﻩ0x02 ﻩ//显示光标#define LCD_NO_CURSORﻩﻩ0x00 //无光标#define LCD_FLASH ﻩ0x01//光标闪动#define LCD_NO_FLASH ﻩ0x00 //光标不闪动void LCD_SetDisplay(unsignedchar DisplayMode){ﻩLCD_Write(LCD_COMMAND, 0x08|DisplayMode);ﻩ}//设置输入模式************************************************************#define LCD_AC_UP ﻩ0x02#define LCD_AC_DOWNﻩﻩ0x00 // default#define LCD_MOVEﻩﻩ0x01 // 画面可平移#define LCD_NO_MOVE ﻩ0x00 //defaultvoid LCD_SetInput(unsigned char InputMode){ﻩLCD_Write(LCD_COMMAND, 0x04|InputMode);}//初始化LCD************************************************************void LCD_Initial(){LcdEn=0;ﻩLCD_Write(LCD_COMMAND,0x38);//8位数据端口,2行显示,5*7点阵LCD_Write(LCD_COMMAND,0x38);LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏ﻩLCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动}//液晶字符输入的位置************************void GotoXY(unsigned char x,unsigned char y){ﻩif(y==0)ﻩﻩLCD_Write(LCD_COMMAND,0x80|x);ﻩif(y==1)ﻩLCD_Write(LCD_COMMAND,0x80|(x-0x40));}//将字符输出到液晶显示void Print(unsigned char *str){while(*str!='\0')ﻩ{ﻩLCD_Write(LCD_DATA,*str);ﻩstr++;}}/***********DS1302时钟部分子程序******************/typedef struct __SYSTEMTIME__{ﻩunsigned char Second;ﻩunsigned char Minute;ﻩunsigned char Hour;unsigned char Week;ﻩunsigned char Day;ﻩunsigned char Month;ﻩunsigned char Year;ﻩunsigned char DateString[11];unsigned charTimeString[9];}SYSTEMTIME;//定义的时间类型SYSTEMTIME CurrentTime;#defineAM(X)ﻩX#define PM(X)ﻩ(X+12) // 转成24小时制#define DS1302_SECONDﻩ0x80 //时钟芯片的寄存器位置,存放时间#define DS1302_MINUTEﻩ0x82#define DS1302_HOUR ﻩ0x84#define DS1302_WEEKﻩ0x8A0x86#define DS1302_DAYﻩﻩ#define DS1302_MONTH 0x88#define DS1302_YEARﻩ 0x8Cvoid DS1302InputByte(unsigned char d) ﻩ//实时时钟写入一字节(内部函数){unsigned char i;ACC = d;for(i=8; i>0;i--){DS1302_IO = ACC0; ﻩ//相当于汇编中的RRC DS1302_CLK = 1;DS1302_CLK = 0;ACC = ACC >> 1;}}unsignedchar DS1302OutputByte(void) //实时时钟读取一字节(内部函数){unsigned char i;for(i=8;i>0; i--){ACC = ACC>>1; ﻩﻩ//相当于汇编中的RRCACC7 = DS1302_IO;DS1302_CLK = 1;DS1302_CLK = 0;}return(ACC);}void Write1302(unsigned char ucAddr, unsigned char ucDa)//ucAddr: DS1302地址, ucData: 要写的数据{DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr); ﻩ// 地址,命令DS1302InputByte(ucDa); ﻩ//写1Byte数据DS1302_CLK = 1;DS1302_RST = 0;}unsignedchar Read1302(unsigned char ucAddr) //读取DS1302某地址的数据{unsignedchar ucData;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr|0x01); // 地址,命令ucData = DS1302OutputByte(); // 读1Byte数据DS1302_CLK = 1;DS1302_RST =0;return(ucData);}void DS1302_GetTime(SYSTEMTIME *Time)//获取时钟芯片的时钟数据到自定义的结构型数组{unsigned char ReadValue;ﻩReadValue = Read1302(DS1302_SECOND);ﻩTime->Second = ((ReadValue&0x70)>>4)*10+ (ReadVal ue&0x0F);ReadValue = Read1302(DS1302_MINUTE);Time->Minute = ((ReadValue&0x70)>>4)*10+ (ReadValue&0x0F);ReadValue = Read1302(DS1302_HOUR);Time->Hour= ((ReadValue&0x70)>>4)*10 +(ReadValue&0x0F);ReadValue = Read1302(DS1302_DAY);Time->Day =((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_WEEK);Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue &0x0F);ReadValue = Read1302(DS1302_MONTH);ﻩTime->Month = ((ReadValue&0x70)>>4)*10 +(ReadValue&0x0F);ﻩReadValue = Read1302(DS1302_YEAR);Time->Year = ((ReadValue&0x70)>>4)*10 +(ReadValu e&0x0F);}void DateToStr(SYSTEMTIME *Time) //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]{ if(hide_year<2) //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为 2007/07/22 {ﻩ Time->DateString[0]= '2';ﻩTime->DateString[1] = '0';Time->DateString[2] = Time->Year/10 + '0';Time->DateString[3] = Time->Year%10 + '0';}else{ﻩ Time->DateString[0] = ' ';Time->DateString[1] = ' ';ﻩﻩﻩ Time->DateString[2] = ' ';ﻩTime->DateString[3] = ' ';ﻩ}ﻩTime->DateString[4]= '/';ﻩif(hide_month<2)ﻩ{ﻩ Time->DateString[5] =Time->Month/10+ '0';Time->DateString[6] =Time->Month%10 + '0';ﻩ}else{ﻩ Time->DateString[5] = ' ';Time->DateString[6] = '';}Time->DateString[7] = '/';if(hide_day<2){Time->DateString[8] = Time->Day/10+'0';Time->DateString[9] =Time->Day%10 +'0';}ﻩelse{ﻩTime->DateString[8]= ' ';ﻩTime->DateString[9]= ' ';}if(hide_week<2)ﻩ{week_value[0] = Time->Week%10 + '0'; //星期的数据另外放到 week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示ﻩ}ﻩelseﻩ {week_value[0] = ' ';ﻩ}week_value[1] = '\0';ﻩTime->DateString[10] = '\0'; //字符串末尾加'\0' ,判断结束字符}void TimeToStr(SYSTEMTIME *Time) //将时,分,秒数据转换成液晶显示字符放到数组 TimeString[];{ if(hide_hour<2){ﻩ Time->TimeString[0] = Time->Hour/10 + '0';ﻩ Time->TimeString[1]= Time->Hour%10 + '0';ﻩ}else{ﻩ Time->TimeString[0] = ' ';ﻩ Time->TimeString[1] = ' ';}Time->TimeString[2] = ':';if(hide_min<2)ﻩ{Time->TimeString[3]= Time->Minute/10 + '0';Time->TimeString[4] =Time->Minute%10 + '0';}ﻩ elseﻩ{Time->TimeString[3] = ' ';ﻩTime->TimeString[4] =' ';ﻩ }ﻩTime->TimeString[5] = ':';if(hide_sec<2){ﻩTime->TimeString[6] = Time->Second/10 + '0';ﻩ Time->TimeString[7] = Time->Second%10 + '0';}else{Time->TimeString[6] = ' ';ﻩTime->TimeString[7] = ' ';}Time->DateString[8] = '\0';}void Initial_DS1302(void) //时钟芯片初始化{unsigned char Second=Read1302(DS1302_SECOND);ﻩif(Second&0x80)//判断时钟芯片是否关闭{ﻩWrite1302(0x8e,0x00); //写入允许Write1302(0x8c,0x07);//以下写入初始化时间日期:07/07/25.星期: 3. 时间: 23:59:55ﻩWrite1302(0x88,0x07);ﻩWrite1302(0x86,0x25);Write1302(0x8a,0x07);ﻩWrite1302(0x84,0x23);Write1302(0x82,0x59);Write1302(0x80,0x55);ﻩWrite1302(0x8e,0x80); //禁止写入}}/***********ds18b20子程序*************************//***********ds18b20延迟子函数(晶振12MHz )*******/void delay_18B20(unsignedint i){while(i--);}/**********ds18b20初始化函数**********************/void Init_DS18B20(void){ﻩ unsigned char x=0;DQ=1;//DQ复位ﻩdelay_18B20(8); //稍做延时ﻩDQ = 0; //单片机将DQ拉低ﻩ delay_18B20(80); //精确延时大于 480usDQ = 1; //拉高总线delay_18B20(14);ﻩ x=DQ; //稍做延时后如果x=0则初始化成功x=1则初始化失败delay_18B20(20);}/***********ds18b20读一个字节**************/unsigned char ReadOneChar(void){uchar i=0;ﻩuchardat = 0;for (i=8;i>0;i--){DQ = 0;// 给脉冲信号dat>>=1;ﻩDQ=1; //给脉冲信号ﻩ if(DQ)ﻩ dat|=0x80;ﻩ delay_18B20(4);}return(dat);}/*************ds18b20写一个字节****************/void WriteOneChar(uchar dat){unsigned char i=0;for(i=8; i>0; i--){ﻩDQ = 0;ﻩDQ= dat&0x01;ﻩdelay_18B20(5);ﻩﻩDQ = 1;ﻩdat>>=1;}}/**************读取ds18b20当前温度************/void ReadTemp(void){unsigned char a=0;ﻩunsignedchar b=0;ﻩunsigned char t=0;ﻩInit_DS18B20();WriteOneChar(0xCC); // 跳过读序号列号的操作WriteOneChar(0x44); ﻩ//启动温度转换ﻩdelay_18B20(100); // this message is wery importantInit_DS18B20();WriteOneChar(0xCC); ﻩ//跳过读序号列号的操作ﻩWriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度ﻩdelay_18B20(100);a=ReadOneChar();//读取温度值低位ﻩb=ReadOneChar();ﻩﻩ//读取温度值高位ﻩtemp_value=b<<4;temp_value+=(a&0xf0)>>4;}void temp_to_str() //温度数据转换成液晶字符显示{TempBuffer[0]=temp_value/10+'0'; //十位TempBuffer[1]=temp_value%10+'0'; //个位TempBuffer[2]=0xdf; //温度符号TempBuffer[3]='C';TempBuffer[4]='\0';}void Delay1ms(unsigned intcount){unsigned int i,j;for(i=0;i<count;i++)for(j=0;j<120;j++);}/*延时子程序*/void mdelay(uint delay){ﻩuint i;for(;delay>0;delay--)ﻩﻩ{for(i=0;i<62;i++) //1ms延时.ﻩ{;}ﻩ}}void outkey() //跳出调整模式,返回默认显示{ uchar Second;if(out==0||wireless_1==1){ mdelay(8);ﻩcount=0;ﻩhide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_month=0,hide_year=0;Second=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入允许Write1302(0x80,Second&0x7f);Write1302(0x8E,0x80); //禁止写入done=0;ﻩwhile(out==0);while(wireless_1==1);}}//////////////////////////////////////////////////////////////////////////////////////////////////////////// void Upkey()//升序按键{ﻩUp=1;if(Up==0||wireless_2==1)ﻩﻩ {ﻩﻩﻩ mdelay(8);ﻩ switch(count)ﻩﻩﻩ{case1:temp=Read1302(DS1302_SECOND); //读取秒数ﻩﻩﻩﻩﻩﻩtemp=temp+1; //秒数加1up_flag=1;//数据调整后更新标志if((temp&0x7f)>0x59) //超过59秒,清零temp=0; ﻩﻩﻩﻩﻩﻩ break;ﻩﻩ case 2:temp=Read1302(DS1302_MINUTE); //读取分数ﻩﻩﻩﻩﻩ temp=temp+1;//分数加1up_flag=1;ﻩﻩﻩﻩ if(temp>0x59) //超过59分,清零ﻩﻩtemp=0;ﻩﻩﻩbreak;ﻩﻩﻩcase 3:temp=Read1302(DS1302_HOUR); //读取小时数ﻩﻩﻩ temp=temp+1; //小时数加1up_flag=1;ﻩﻩﻩﻩﻩﻩif(temp>0x23) //超过23小时,清零ﻩﻩﻩﻩﻩﻩtemp=0;ﻩﻩﻩﻩbreak;ﻩﻩﻩﻩcase 4:temp=Read1302(DS1302_WEEK); //读取星期数ﻩﻩﻩﻩ temp=temp+1; //星期数加1up_flag=1;ﻩﻩﻩ if(temp>0x7)ﻩﻩﻩﻩ temp=1;ﻩﻩﻩﻩﻩﻩ break;ﻩcase 5:temp=Read1302(DS1302_DAY); //读取日数ﻩﻩﻩ temp=temp+1; //日数加1up_flag=1;ﻩﻩﻩﻩ if(temp>0x31)ﻩﻩﻩﻩﻩﻩ temp=1;ﻩﻩﻩﻩ break;ﻩﻩcase 6:temp=Read1302(DS1302_MONTH); //读取月数ﻩﻩﻩﻩtemp=temp+1; //月数加1up_flag=1;ﻩﻩﻩﻩﻩﻩﻩif(temp>0x12)ﻩﻩﻩﻩ temp=1;ﻩﻩﻩﻩ break;ﻩcase 7:temp=Read1302(DS1302_YEAR);//读取年数ﻩﻩﻩﻩﻩﻩﻩ temp=temp+1; //年数加1up_flag=1;ﻩﻩﻩﻩif(temp>0x85)ﻩﻩﻩﻩﻩ temp=0;ﻩﻩ break;ﻩﻩﻩﻩdefault:break;ﻩ }ﻩﻩﻩ while(Up==0);ﻩ while(wireless_2==1);}}////////////////////////////////////////////////////////////////////////////////////////////////////////////void Downkey()//降序按键{ﻩﻩﻩDown=1;if(Down==0||wireless_3==1)ﻩ {ﻩﻩﻩmdelay(8);ﻩﻩ switch(count)ﻩﻩ {case 1:temp=Read1302(DS1302_SECOND); //读取秒数ﻩﻩﻩﻩﻩtemp=temp-1;ﻩ//秒数减1down_flag=1; //数据调整后更新标志ﻩﻩﻩﻩ if(temp==0x7f) //小于0秒,返回59秒ﻩﻩtemp=0x59;ﻩﻩbreak;ﻩﻩﻩ case2:temp=Read1302(DS1302_MINUTE); //读取分数ﻩﻩﻩtemp=temp-1; //分数减1down_flag=1;ﻩﻩﻩﻩ if(temp==-1)ﻩﻩﻩﻩﻩﻩ temp=0x59; //小于0秒,返回59秒ﻩﻩﻩﻩﻩ break;case 3:temp=Read1302(DS1302_HOUR); //读取小时数ﻩﻩﻩtemp=temp-1; //小时数减1down_flag=1;ﻩﻩﻩﻩ if(temp==-1)ﻩtemp=0x23;ﻩﻩ break;ﻩ case 4:temp=Read1302(DS1302_WEEK);//读取星期数ﻩﻩﻩﻩ temp=temp-1; //星期数减1down_flag=1;ﻩﻩﻩﻩ if(temp==0)ﻩﻩﻩﻩﻩ temp=0x7;;ﻩﻩﻩ break;ﻩ case 5:temp=Read1302(DS1302_DAY); //读取日数ﻩﻩﻩﻩﻩ temp=temp-1; //日数减1down_flag=1;ﻩﻩﻩﻩ if(temp==0)ﻩﻩﻩtemp=31;ﻩﻩ break;ﻩﻩﻩ case 6:temp=Read1302(DS1302_MONTH); //读取月数ﻩﻩﻩﻩﻩﻩ temp=temp-1; //月数减1down_flag=1;ﻩif(temp==0)ﻩﻩﻩﻩﻩ temp=12;ﻩﻩﻩﻩﻩﻩ break;ﻩﻩcase 7:temp=Read1302(DS1302_YEAR);//读取年数ﻩﻩﻩﻩ temp=temp-1; //年数减1down_flag=1;ﻩﻩﻩﻩ if(temp==-1)ﻩﻩﻩtemp=0x85;ﻩﻩﻩﻩﻩﻩﻩ break;ﻩﻩ default:break;ﻩ}ﻩﻩﻩﻩwhile(Down==0);ﻩﻩwhile(wireless_3==1);ﻩ}}void Setkey()//模式选择按键{ﻩSet=1;ﻩif(Set==0||wireless_4==1)ﻩ{mdelay(8);count=count+1; //Setkey按一次,count就加1 done=1; ﻩﻩ//进入调整模式while(Set==0);while(wireless_4==1);ﻩ }}void keydone()//按键功能执行{ uchar Second;ﻩ if(flag==0) //关闭时钟,停止计时{ Write1302(0x8e,0x00); //写入允许temp=Read1302(0x80);Write1302(0x80,temp|0x80);ﻩWrite1302(0x8e,0x80); //禁止写入flag=1;}Setkey(); ﻩ//扫描模式切换按键ﻩswitch(count)ﻩﻩ {case 1:do ﻩ //count=1,调整秒{outkey();ﻩﻩ //扫描跳出按钮ﻩﻩﻩUpkey(); //扫描加按钮ﻩﻩ Downkey(); //扫描减按钮ﻩﻩﻩﻩif(up_flag==1||down_flag==1) //数据更新,重新写入新的数据{ﻩﻩ Write1302(0x8e,0x00); //写入允许ﻩﻩﻩWrite1302(0x80,temp|0x80); //写入新的秒数ﻩﻩﻩWrite1302(0x8e,0x80); //禁止写入ﻩﻩﻩ up_flag=0;ﻩﻩﻩﻩ down_flag=0;ﻩﻩ}ﻩhide_sec++; //位闪计数ﻩﻩif(hide_sec>3)ﻩﻩ hide_sec=0;show_time(); //液晶显示数据ﻩﻩﻩﻩ}while(count==2);break;ﻩ case 2:doﻩﻩ//count=2,调整分ﻩ {ﻩﻩhide_sec=0;ﻩ outkey();ﻩﻩﻩ Upkey();ﻩﻩ Downkey();ﻩﻩ if(temp>0x60)ﻩﻩ temp=0;ﻩﻩﻩ if(up_flag==1||down_flag==1)ﻩﻩ {ﻩWrite1302(0x8e,0x00); //写入允许ﻩﻩﻩ Write1302(0x82,temp); //写入新的分数ﻩWrite1302(0x8e,0x80);//禁止写入ﻩ up_flag=0;ﻩ down_flag=0;ﻩﻩﻩ }ﻩﻩ hide_min++;ﻩﻩ if(hide_min>3)ﻩﻩﻩhide_min=0;show_time();ﻩﻩ }while(count==3);break;ﻩ case 3:doﻩﻩﻩﻩ//count=3,调整小时ﻩﻩ{hide_min=0;ﻩoutkey();ﻩUpkey();ﻩ Downkey();ﻩﻩﻩ if(up_flag==1||down_flag==1)ﻩﻩ{ﻩﻩﻩ Write1302(0x8e,0x00); //写入允许ﻩ Write1302(0x84,temp); //写入新的小时数ﻩﻩ Write1302(0x8e,0x80); //禁止写入ﻩﻩﻩ up_flag=0;ﻩ down_flag=0;ﻩ}hide_hour++;ﻩﻩif(hide_hour>3)hide_hour=0;show_time();ﻩﻩ }while(count==4);break;case 4:doﻩﻩﻩﻩ //count=4,调整星期ﻩ {hide_hour=0;outkey();Upkey();ﻩﻩDownkey();ﻩ if(up_flag==1||down_flag==1)ﻩﻩ{ﻩ Write1302(0x8e,0x00); //写入允许ﻩﻩﻩﻩ Write1302(0x8a,temp); //写入新的星期数ﻩﻩWrite1302(0x8e,0x80); //禁止写入ﻩﻩ up_flag=0;ﻩﻩ down_flag=0;ﻩﻩ}ﻩhide_week++;ﻩﻩ if(hide_week>3)ﻩﻩﻩ hide_week=0;show_time();ﻩﻩﻩ }while(count==5);break;ﻩ case 5:doﻩﻩﻩﻩﻩ//count=5,调整日ﻩ {ﻩﻩﻩﻩ hide_week=0;ﻩoutkey();ﻩﻩﻩﻩ Upkey();ﻩﻩ Downkey();ﻩﻩﻩ if(up_flag==1||down_flag==1)ﻩﻩ{ﻩ Write1302(0x8e,0x00); //写入允许Write1302(0x86,temp); //写入新的日数ﻩﻩﻩ Write1302(0x8e,0x80); //禁止写入ﻩﻩﻩ up_flag=0;ﻩ down_flag=0;ﻩ}ﻩﻩﻩ hide_day++;ﻩﻩﻩif(hide_day>3)ﻩ hide_day=0;show_time();ﻩﻩ }while(count==6);break;ﻩﻩcase 6:doﻩﻩﻩﻩﻩ//count=6,调整月{hide_day=0;ﻩﻩﻩﻩ outkey();ﻩﻩ Upkey();ﻩﻩ Downkey();ﻩﻩ if(up_flag==1||down_flag==1)ﻩﻩ {ﻩﻩ Write1302(0x8e,0x00); //写入允许ﻩﻩ Write1302(0x88,temp); //写入新的月数ﻩ Write1302(0x8e,0x80); //禁止写入ﻩup_flag=0;ﻩﻩﻩ down_flag=0;ﻩﻩ}ﻩﻩ hide_month++;ﻩﻩif(hide_month>3)ﻩﻩﻩ hide_month=0;show_time();ﻩ }while(count==7);break;ﻩﻩ case 7:doﻩ//count=7,调整年{hide_month=0;ﻩﻩﻩ outkey();ﻩﻩUpkey();ﻩﻩDownkey();ﻩ if(up_flag==1||down_flag==1)ﻩﻩ {ﻩ Write1302(0x8e,0x00); //写入允许ﻩﻩWrite1302(0x8c,temp); //写入新的年数Write1302(0x8e,0x80); //禁止写入ﻩﻩ up_flag=0;ﻩﻩdown_flag=0;ﻩﻩﻩﻩ }ﻩﻩﻩhide_year++;ﻩif(hide_year>3)ﻩﻩﻩ hide_year=0;show_time();ﻩﻩ}while(count==8);break;ﻩ case 8: count=0;hide_year=0; //count8,跳出调整模式,返回默认显示状态ﻩSecond=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入允许ﻩ Write1302(0x80,Second&0x7f);ﻩ Write1302(0x8E,0x80); //禁止写入ﻩﻩﻩ done=0;ﻩﻩ break; //count=7,开启中断,标志位置0并退出ﻩ default:break;ﻩ }}void show_time() //液晶显示程序{DS1302_GetTime(&CurrentTime);//获取时钟芯片的时间数据TimeToStr(&CurrentTime); //时间数据转换液晶字符DateToStr(&CurrentTime); //日期数据转换液晶字符ReadTemp(); //开启温度采集程序temp_to_str(); //温度数据转换成液晶字符GotoXY(12,1); //液晶字符显示位置Print(TempBuffer); //显示温度GotoXY(0,1);Print(CurrentTime.TimeString); //显示时间GotoXY(0,0);Print(CurrentTime.DateString); //显示日期GotoXY(15,0);Print(week_value); //显示星期GotoXY(11,0);Print("Week");ﻩ//在液晶上显示字母 weekDelay1ms(400); //扫描延时}main(){flag=1; //时钟停止标志LCD_Initial(); //液晶初始化Init_DS18B20( ) ; //DS18B20初始化Initial_DS1302(); //时钟芯片初始化up_flag=0;down_flag=0;ﻩdone=0; //进入默认液晶显示ﻩwireless_1=0;wireless_2=0;ﻩwireless_3=0;wireless_4=0;while(1){while(done==1)keydone(); //进入调整模式while(done==0)ﻩ{show_time(); //液晶显示数据flag=0;ﻩﻩ Setkey(); ﻩﻩ //扫描各功能键ﻩﻩ}}}。
毕业论文用DS1302与1602LCD设计的可调式电子日历时钟的设计与实现 .jsp
中州大学信息工程学院毕业设计(论文)2009 — 2010学年第二学期题目:用DS1302与1602设计的可调式电子日历时钟的设计与实现学生姓名(学号)邱进进(200702131071171)指导教师刘爱荣职称教授评阅教师职称时间中州大学信息工程学院毕业设计(论文)任务书指导教师:刘爱荣职称:教授学生人数:1人学生姓名(学号、专业):07电子班邱进进毕业设计(论文)题目(来源、类型)用DS1302与1602LCD设计的可调式电子日历时钟的设计与实现毕业设计(论文)工作内容与基本要求(目标、任务、途径、方法、成果形式,应掌握的原始资料(数据)、参考资料(文献)以及设计技术要求、注意事项等)(纸张不够可加页)基本要求:(1)显示:年、月、日、时、分、秒;(2)具有年、月、日、时、分、秒的设置功能。
成果形式:(主要包括毕业论文,系统设计技术文档,软件等):设计功能演示;论文电子文档及程序提交光盘;按学院格式要求打印论文3份上交。
参考资料有:单片机的C语言应用程序设计(马忠梅、)新编单片机应用程序设计(张毅刚)教研室审批意见:审批人签名:中州大学信息工程学院毕业设计(论文)开题报告课题名称(来源、类型):用DS1302与1602LCD设计的可调式电子日历时钟的设计与实现指导教师:刘爱荣学生姓名:邱进进200702131071171专业:07电子信息工程技术开题报告内容:(调研资料的准备,设计/论文的目的、要求、思路与预期成果;任务完成的阶段内容及时间安排;完成设计(论文)所具备的条件因素等。
)1.目的:实现日历和时钟的显示并且能够调整2.要求:完成可调式电子日历时钟的硬件和软件的设计,包括单片机的相关内容;日历时钟模块的设计,液晶显示模块的设计,按键模块的设计。
控制程序的编写等。
3.预期成果:仿真成功,做出实物产品。
(1)显示初始值日历时钟初始值;(2)用按键调整日历时钟。
4.时间安排:第1~2周:熟悉课题的基本要求,查阅相关资料,初步拟定设计的整体方案,完成开题报告。
电子钟课程设计报告DS1302,LCD1602,AT89C52
实验总成绩: __________报告份数:1份西安邮电大学通信与信息工程学院课程设计实验报告专业班级:_________________学生姓名:__________________________学号(班内序号): ____________ 年—月—日成绩鉴定表、设计任务和目的1.用单片机设计基于STC89C52, DS1302, LCD 1602的电子钟,显示时间和日期2.具有时间和日期的校准,记忆功能3.搭建仿真电路,模拟要实现的功能4.焊接单片机实物5.熟练掌握相关软件的使用方法,以及各个器件的基本工作原理6•编写程序,下载并调试,实现要求的功能二、设计思路和方案电路整体上分为控制和显示部分,以单片机最小系统为核心电路,控制LCD 显示,具体的显示内容和方式由软件来完成;由于有时钟和H期的调节功能需要校准电路和基本的复位电路,复位电路采用按键复位,调节键、加1键、减1键,共四键,计时功能由DS1302 完成,显示功能则由LCD 1602液晶完成三.基本设计原理该电子时钟是利用单片机内部的定时器\计数器来实现的,它的处理过程如下:首先设定单片机内部的一个定时器\计数器工作于定时方式,对机器周期计数形成基准时间,然后用另一个定时器\计数器或软件计数的方法对基准时间计数形成秒,秒计60次形成分,分计60次形成小时,小时计24次则计满一天。
然后通过LCD1602液晶把它们的内容在相应位置显示出来即可。
译码方式可分为软件译码和硬件译码,软件译码通过译码程序查得显示信息的字段码;硬件译码通过硬件译码器得到显示信息的字段码,实际中通常采用软件译码。
在具体处理时,定时器计数器采用中断方式工作,对时钟的形成在中断服务程序中实现。
在主程序中只需对定时器计数器初始化、调用显示子程序和控制子程序。
另外,为了使用方便,设计了简单的按键,可以通过按键实现时、分和H期的调整,这样在主程序中就加入了键盘设置子程序。
由于使用了时间记忆芯片DS1302故断电后下次通电时间能够保持不变,更加的合理人性化。
单片机万年历的实训报告
一、实训背景随着科技的不断发展,单片机技术在各个领域得到了广泛的应用。
单片机具有体积小、功耗低、成本低、可靠性高等优点,因此在智能仪表、工业控制、家用电器等领域具有很高的应用价值。
万年历作为一种时间记录工具,在日常生活中有着广泛的应用。
本实训旨在通过单片机万年历的设计与实现,提高学生对单片机编程和硬件应用能力的培养。
二、实训目的1. 熟悉单片机的基本原理和编程方法;2. 掌握万年历的设计与实现方法;3. 提高学生的动手能力和实践能力;4. 培养学生的创新意识和团队协作精神。
三、实训内容1. 单片机万年历硬件设计(1)单片机核心:选用AT89C51单片机作为核心控制器,其具有丰富的I/O接口,便于与其他外围电路连接。
(2)时钟芯片:选用DS1302时钟芯片,用于存储和提供系统时间,具有年、月、日、时、分、秒等信息。
(3)显示模块:选用LCD1602液晶显示屏,用于显示年、月、日、时、分、秒、星期等信息。
(4)按键模块:选用独立按键,用于设置和调整时间、日期、星期等信息。
(5)温度传感器:选用DS18B20数字温度传感器,用于检测环境温度。
2. 单片机万年历软件设计(1)系统初始化:对单片机进行初始化,设置时钟频率、I/O端口等。
(2)时钟读取与显示:从DS1302时钟芯片读取时间,并在LCD1602显示屏上显示。
(3)按键处理:对按键进行扫描和处理,实现时间、日期、星期等信息的设置和调整。
(4)温度检测与显示:从DS18B20温度传感器读取温度,并在LCD1602显示屏上显示。
(5)温度报警:当温度超过设定值时,通过蜂鸣器发出报警信号。
3. 单片机万年历功能实现(1)显示年、月、日、时、分、秒、星期等信息。
(2)设置和调整时间、日期、星期等信息。
(3)显示环境温度。
(4)温度报警功能。
四、实训结果与分析1. 硬件电路搭建成功,实现了万年历的基本功能。
2. 软件编程完成,实现了万年历的时间显示、按键处理、温度检测与显示、温度报警等功能。
基于DS1302和LCD1602的万年历,闹钟,时钟,用开发版直接显示的程序 - 副本
实时时钟芯片DS1302应用,DS18B20应用实例——可调时钟,LCD1602显示:(时间+温度)说明:需要按程序中定义的接口。
按自己接口,只要在程序中修改接口定义即可。
1、DS1302引脚排列:如下图引脚说明:1)Vcc1:后备电源,VCC2:主电源。
在主电源关闭的情况下,也能保持时钟的连续运行。
DS1302由Vcc1或Vcc2两者中的较大者供电。
当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。
当Vcc2小于Vcc1时,DS1302由Vcc1供电。
2)X1、X2:振荡源,外接32.768kHz 晶振。
3)RST:复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。
RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。
当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。
如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。
上电运行时,在Vcc>2.0V之前,RST必须保持低电平。
只有在SCLK为低电平时,才能将RST置为高电平。
4)I/O为串行数据输入输出端(双向)。
5)SCLK为时钟输入端。
2、 DS1302的控制字节DS1302 的控制字如下图所示。
控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。
3、数据输入输出(I/O)在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
基于DS1302和LCD1602的数字电子钟设计
基于DS1302与LCD1602的数字电子钟设计The design of digital electric clock based on theDS1302 and LCD1602摘要:本文主要介绍基于AT89S52单片机微处理芯片与DS1302时钟芯片和LCD1602液晶显示模块组成的数字式电子时钟的电路软硬件设计。
可以精确调整年、月、日以及小时、分钟和秒的信息。
该电子时钟具有走时准确、系统掉电时间数据不丢失、功耗低等特点。
并可用于其他对时间有要求的控制系统。
Abstract:This paper mainly introduces the hardware and software design of digital electronic clock which is made up of the AT89S52 MCU ,DS1302 clock chip and LCD1602 module .It can accurately adjust the information of the year,month,day,hour,minutes and seconds.This electronic clock has the characteristics of working accurately,keeping the time date when system losing power, and low power consumptions.关键词:单片机;DS1302;LCD1602;数字时钟Keywords: singlechip;DS1302;LCD1602;Digital clock一.引言1.DS1302时钟芯片简介[1]DS1302是美国DALLAS公司推出的一种高性能、低功耗的具有涓流充电功能的实时时钟芯片。
因具有其价格低廉、性能稳定的优点而被广泛应用于对时间精度有较高要求的各种智能化仪器仪表中。
基于DS1302和LCD1602的万年历系统设计
基于DS1302和LCD1602的万年历系统设计
任志敏
【期刊名称】《电脑开发与应用》
【年(卷),期】2015(000)003
【摘要】This paper introduces the design of a calendar system that contained C51 single-chip, calendar chip DS1302, display module LCD1602 and touch switches. The system is low cost, universal, and easy to implement. The system scheme, hardware scheme, software are also designed.%以低成本、通用性、可操作性为原则,设计了以C51单片机为控制器,集时钟芯片DS1302,显示屏LCD1602,轻触开关为一体的万年历系统。
在设计
该系统总体方案的基础上,完成了该系统的原理图、软件和实物设计。
【总页数】3页(P28-30)
【作者】任志敏
【作者单位】常州纺织服装职业技术学院机电工程系,江苏常州 213164
【正文语种】中文
【中图分类】N945.23
【相关文献】
1.LCD1602汉字显示技术在万年历中的应用及Proteus仿真 [J], 李建波
2.基于CPLD的LCD1602显示系统设计与实现 [J], 陈海峰;丁丽丽
3.基于STM32的电子万年历系统设计 [J], 刘磊
4.基于时钟芯片DS1302的万年历的设计 [J], 李伟跃
5.万年历芯片DS1302功能测试方法研究 [J], 张春宇
因版权原因,仅展示原文概要,查看原文内容请购买。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
利用时钟芯片DS1302实现万年历系别电子通信工程系组别第十组专业名称电子信息工程指导教师组内成员2013年8月19日用DS1302与LCD1602设计的可调式电子日历时钟一、总体设计1.1、设计目的为巩固所学的单片机知识,把所学理论运用到实践中,用LCD1602与DS1302 设计可调式电子日历时钟。
1.2、设计要求(1)显示:年、月、日、时、分、秒和星期;(2)设置年、月、日、时、分、秒和星期的初始状态;(3)能够用4个按键调整日历时钟的年、月、日、时、分、秒和星期;完成可调式电子日历时钟的硬件和软件的设计,包括单片机的相关内容;日历时钟模块的设计,液晶显示模块的设计,按键模块的设计。
控制程序的编写等。
备注:本程序另外添加了每到上午8:10和下午2:10的闹钟提醒功能。
1.3、系统基本方案选择和论证1.3.1、单片机芯片的选择方案方案一:采用89C51芯片作为硬件核心,采用Flash ROM,内部具有4KB ROM 存储空间,能于3V的超低压工作,而且与MCS-51系列单片机完全兼容。
方案二:采用STC12C5A60S2系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,是高速/低功耗/超强抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8-12倍。
内部集成MAX810专用复位电路,2路PWM,8路高速10位A/D转换(250K/S),针对电机控制,强干扰场合。
但造价较高。
1.3.2 、显示模块选择方案和论证:方案一:采用点阵式数码管显示,点阵式数码管是由八行八列的发光二极管组成,对于显示文字比较适合,如采用显示数字显得太浪费,且价格也相对较高。
所以不用此种作为显示。
方案二:采用LED数码管动态扫描,虽然LED数码管价格适中,但要显示多个数字所需要的个数偏多,功耗较大,显示出来的只是拼音,而不是汉字。
所以也不用此种作为显示。
方案三:采用LCD液晶显示屏,液晶显示屏的显示功能强大,可显示大量字符,且视觉效果较好,外形美观。
LCD1602可实现显示2行十六个字符。
1.3.3、时钟芯片的选择方案和论证:方案一:直接采用单片机定时计数器提供秒信号,使用程序实现年、月、日、星期、时、分、秒计数。
采用此种方案虽然减少芯片的使用,节约成本,但是,实现的时间误差较大。
所以不采用此方案。
方案二:采用DS1302时钟芯片实现时钟,DS1302芯片是一种高性能的时钟芯片,可自动对秒、分、时、日、星期、月、年以及闰年补偿的年进行计数,而且精度高,31*8位的RAM做为数据暂存区,工作电压范围为2.5V~5.5V,2.5V时耗电小于300nA。
1.3.4、电路设计最终方案决定综上各方案所述,对此次作品的方案选定:采用80C51作为主控制系统;DS1302提供时钟;LCD1602液晶带汉字库显示屏作为显示部分。
二、硬件设计2.1、电路设计模块图如图2-1所示80C51主控制器模 块LCD 显示控制模块按键控制模块蜂鸣器闹钟提醒控制模块DS1302实时时钟控制模块图 2-12.2、系统总体设计原理图2.3、要求用proteus仿真软件仿真并抓图。
三、软件设计3.1、画出各个函数流程图。
3.1.1、DS1302实时控制芯片的流程图如图3-1开始初始时间状态设置向DS1302中写日期时间从DS1302中读日期时间送到80C51图3-13.1.2、LCD1602液晶显示控制流程图如图3-2入口对1602初始化写入显示设置命令延时一段时间检查忙标志是BF= 7>?设置字符显示位置延时一段时间向1602中写入数据LCD显示内容返回主程序图3-23.1.3、闹钟提醒控制流程如图3-3开始查询是否到定时时间P3_7置低蜂鸣器响应闹铃否是如图3-33.1.4、调时函数控制流程如图3-4开始控制键有效,调整年等待按键程序加有效减有效年加1 年减1控制键有效,调整月等待按键程序加有效减有效月加1 月减1控制键有效,调整日控制键有效,调整星期等待按键程序等待按键程序加有效减有效日加1 日减1 加有效减有效星期加 1 星期减 1控制键有效,调整时控制键有效,调整分加有效减有效加有效减有效时加1 时减1按键有效跳出调时程序,进入主循环分减1分加1等待按键程序等待按键程序图3-33.2、写出程序代码。
/*说明********************************************************************* *****曲谱存贮格式unsigned char code MusicName{音高,音长,音高,音长...., 0,0};末尾:0,0 表示结束(Important)音高由三位数字组成:个位是表示1~7 这七个音符十位是表示音符所在的音区:1-低音,2-中音,3-高音;百位表示这个音符是否要升半音: 0-不升,1-升半音。
音长最多由三位数字组成:个位表示音符的时值,其对应关系是:|数值(n): |0 |1 |2 |3 | 4 | 5 | 6|几分音符: |1 |2 |4 |8 |16 |32 |64 音符=2^n十位表示音符的演奏效果(0-2): 0-普通,1-连音,2-顿音百位是符点位: 0-无符点,1-有符点调用演奏子程序的格式Play(乐曲名,调号,升降八度,演奏速度);|乐曲名: 要播放的乐曲指针,结尾以(0,0)结束;|调号(0-11) : 是指乐曲升多少个半音演奏;|升降八度(1-3) : 1:降八度, 2:不升不降, 3:升八度;|演奏速度(1-12000): 值越大速度越快;********************************************************************* ******/#include "buzz.h"unsigned int code FreTab[12] = { 262,277,294,311,330,349,369,392,415,440,466,494 }; //原始频率表unsigned char code SignTab[7] = { 0,2,4,5,7,9,11 };//1~7在频率表中的位置unsigned char code LengthTab[7]= { 1,2,4,8,16,32,64 };static unsigned char Sound_Temp_TH0,Sound_Temp_TL0; //音符定时器初值暂存static unsigned char Sound_Temp_TH1,Sound_Temp_TL1; //音长定时器初值暂存extern int8 scan_key(void);void InitialSound(void){BeepIO = 1;Sound_Temp_TH1 = (65535-(1/1200)*SYSTEM_OSC)/256; // 计算TL1应装入的初值(10ms的初装值)Sound_Temp_TL1 = (65535-(1/1200)*SYSTEM_OSC)%256; // 计算TH1应装入的初值TH1 = Sound_Temp_TH1;TL1 = Sound_Temp_TL1;TMOD |= 0x11;ET0 = 1;ET1 = 0;TR0 = 0;TR1 = 0;EA = 1;}void BeepTimer0(void) interrupt 1 //音符发生中断{BeepIO = !BeepIO;TH0 = Sound_Temp_TH0;TL0 = Sound_Temp_TL0;}//******************************************************************** ******bit Play(unsigned char *Sound,unsigned char Signature,unsigned Octachord,unsigned int Speed){unsigned int NewFreTab[12]; //新的频率表unsigned char i,j;unsigned int Point,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;unsigned char Tone,Length,SL,SH,SM,SLen,XG,FD;for(i=0;i<12;i++) // 根据调号及升降八度来生成新的频率表{j = i + Signature;if(j > 11){j = j-12;NewFreTab[i] = FreTab[j]*2;}elseNewFreTab[i] = FreTab[j];if(Octachord == 1)NewFreTab[i]>>=2;else if(Octachord == 3)NewFreTab[i]<<=2;}SoundLength = 0;while(Sound[SoundLength] != 0x00) //计算歌曲长度{SoundLength+=2;}Point = 0;Tone = Sound[Point];Length = Sound[Point+1]; // 读出第一个音符和它时时值LDiv0 = 12000/Speed; // 算出1分音符的长度(几个10ms)LDiv4 = LDiv0/4; // 算出4分音符的长度LDiv4 = LDiv4-LDiv4*SOUND_SPACE; // 普通音最长间隔标准TR0 = 0;TR1 = 1;while(Point < SoundLength){if (scan_key()){BeepIO = 1;return 0;}SL=Tone%10; //计算出音符SM=Tone/10%10; //计算出高低音SH=Tone/100; //计算出是否升半CurrentFre = NewFreTab[SignTab[SL-1]+SH]; //查出对应音符的频率if(SL!=0){if (SM==1) CurrentFre >>= 2; //低音if (SM==3) CurrentFre <<= 2; //高音Temp_T = 65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC);//计算计数器初值Sound_Temp_TH0 = Temp_T/256;Sound_Temp_TL0 = Temp_T%256;TH0 = Sound_Temp_TH0;TL0 = Sound_Temp_TL0 + 12; //加12是对中断延时的补偿}SLen=LengthTab[Length%10]; //算出是几分音符XG=Length/10%10; //算出音符类型(0普通1连音2顿音) FD=Length/100;LDiv=LDiv0/SLen; //算出连音音符演奏的长度(多少个10ms) if (FD==1)LDiv=LDiv+LDiv/2;if(XG!=1)if(XG==0) //算出普通音符的演奏长度if (SLen<=4)LDiv1=LDiv-LDiv4;elseLDiv1=LDiv*SOUND_SPACE;elseLDiv1=LDiv/2; //算出顿音的演奏长度elseLDiv1=LDiv;if(SL==0) LDiv1=0;LDiv2=LDiv-LDiv1; //算出不发音的长度if (SL!=0){TR0=1;for(i=LDiv1;i>0;i--) //发规定长度的音{while(TF1==0);TH1 = Sound_Temp_TH1;TL1 = Sound_Temp_TL1;TF1=0;}}if(LDiv2!=0){TR0=0; BeepIO=0;for(i=LDiv2;i>0;i--) //音符间的间隔{while(TF1==0);TH1 = Sound_Temp_TH1;TL1 = Sound_Temp_TL1;TF1=0;}}Point+=2;Tone=Sound[Point];Length=Sound[Point+1];}BeepIO = 1;return 1;}/** 蜂鸣器响*/void alarm_sound(void){uint16 m,n=2000;while (n--){BeepIO = ~BeepIO;for (m=0; m<100; m++);}BeepIO = 1;}四、专业实习要求1、掌握常用设备的使用;2、掌握keil 编译环境的使用,熟悉proteus仿真软件的使用;3、基本掌握电路板的焊接调试技巧;4、基本掌握51单片机最小应用系统的组装、调试。