用DS1302与LCD1602可调数字万年历课程设计
- 格式:doc
- 大小:455.50 KB
- 文档页数:23
学习情境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移动通信工具等众多领域。
C语言Lcd1602万年历闹钟Proteus仿真单片机毕业课程电子设计
C语言Lcd1602万年历闹钟Proteus仿真单片机设计
AT89C51+Lcd1602+DS1302+独立按键+蜂鸣器
Lcd1602万年历闹钟。
时间信息来自DS1302,显示采用
Lcd1602,蜂鸣器提供闹音和按键提示音。
液晶上面显示年月日时分秒星期以及闹钟时间。
有时间调节和闹钟调节,可以调节年月日时分秒星期信息以及闹钟时间。
具体介绍如下。
1.做好的仿真图,如下图所示。
2.启动仿真后,先在液晶屏显示系统信息,然后在第二屏显示需要的万年历闹钟信息。
如下图所示!
3.通过单片机右侧的三个按键,即可设置闹钟。
如下图所示。
4.通过单片机左侧的四个按键,来设置年月日时分秒星期的值。
设置时,参数闪烁,同时会有按键提示音。
5.本设计默认套餐1,具体套餐详情请看下面的发货清单。
如需要其它套餐,请联系客服询问。
详情请:点击此处。
基于51单片机DS1302万年历课程设计报告课程名称:微机原理课程设计题目:基于DS1302芯片万年历摘要DS1302 是DALLAS 公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和31 字节静态RAM,通过简单的串行接口与单片机进行通信实时时钟/日历电路.提供秒、分、时、日、日期.、月、年的信息,每月的天数和闰年的天数可自动调整时钟。
本次课程设计的是使用专门的时钟芯片DS1302在数码管上显示的数字电子钟,并能通过按键对其进行调时和校准以及实现年月日。
DS1302是一种高性能、低功耗、带RAM的实时时钟芯片,它能够对时,分,秒进行精确计时,它与单片机的接口使用同步串行通信,仅用3条线与之相连接,就可以实现STC-51单片机对其进行读写操作,把读出的时间数据送到数码管上显示。
程序运行时,数码管将从当前时间开始显示,通过调节K2键和K3键可以分别对小时和分钟进行调整,调整后,时钟以新的时间为起点继续刷新显示,通过调节K1键可以切换年月日和时钟显示。
关键字:STC-51单片机,DS1302,数码管,动态扫描,调时,切换,秒闪;目录一、设计任务与要求 (4)1.1设计任务 (4)1.2设计要求 (4)1.3发挥部分 (4)1.4创新部分 (4)二、方案总体设计 (5)2.1设计目的 (5)2.2硬件功能描述 (5)2.3设计方案选择 (5)2.4总体设计 (6)2.5总体方案及基本工作原理 (6)三、硬件设计 (7)3.1 STC89C51芯片 (7)3.2电源模块及晶振模块 (7)3.3 DS1302 (8)3.4数码管显示模块 (9)3.5蜂鸣器部分 (10)3.6按键部分 (11)四、软件设计 (13)4.1软件流程图 (13)4.2 软件设计 (13)主函数部分: (13)五、系统仿真和调试 (15)5.1 仿真软件简介 (15)5.2硬件调试 (15)5.3软件调试 (15)5.4使用说明 (16)六、设计总结与体会 (18)6.1学习方面 (18)6.2工作方面 (18)七、参考文献 (19)一、设计任务与要求1.1设计任务DS1302万年历;1.2设计要求利用DS1302生成万年历,时钟可调,通过四位数码管显示,并可实现秒闪功能,同时蜂鸣器闹铃;1.3发挥部分设置按键K3用来切换显示时钟和年月日;1.4创新部分只设置了两个按键K1和K2来调节时分,时钟到24归零,分钟到60归零,分钟有长按迅速调节功能。
电子系统设计实验报告实验目的:1、能够以DS1302实时时钟芯片和液晶显示屏CD1602为基础设计一款电子钟2、熟悉DS1302芯片的工作过程3、熟悉CD1602芯片的工作过程4、可以进行必要的扩展,如用第三DS18B20新品进行温度采集和显示5、熟悉掌握51的c程序的编写6、掌握用Proteus进行系统设计仿真验证实验仪器、仪表目录1、DS1302实时时钟芯片1片2、LCD1602液晶显示屏1个,3、80C52芯片1片5、DS18B20芯片一片6、晶振、电容、电阻、开关各若干等7、proteus仿真软件8、Keil C51、PC机实验设计任务以DS1302实时时钟芯片和液晶显示屏LCD1602为基础设计一个电子钟,要求:时间和日期可调整,按键采用3个按键;至少在Proteus上调试通过。
扩展:闹钟和重要日期提醒功能(增加蜂鸣器),闹铃音乐功能实验步骤1、打开Keil软件,新建一个工程文件,选择好芯片,并记得在“Options for Target 1”的Output 选项中,将Create HEX Fil选项勾起来。
2、将编写的程序保存成“.C”的形式3、编译保存好的C文件,并根据提示修改程序中的错误,直到编译成功为止4、打开proteus软件,画出实验电路图5、在89C52中,载入原来已生成的HEX文档6、按下运行键,对Proteus进行软件仿真,观察运行结果原理、结果及分析一、设计方案原理与设计特点分析电子钟总的设计模块:各个模块电路原理分析:1、DS1302时钟采集模块:1.1电路原理图:1.2 DS1302分析:首先DS1302是DALLAS公司推出的涓流充电时钟芯片。
内含有一个实时时钟/日历和31字节静态RAM通过简单的串行接口与单片机进行通信实时时钟/日历电路提供秒分时日日期月年的信息每月的天数和闰年的天数可自动调整时钟操作。
DS1302芯片广脚介绍:X1、X2为32.768KHz晶振管脚。
单片机设计实验内容摘要:单片机实验是通过Proteus仿真并且与Keil相结合使用控制单片机使其在仿真中完成一系列所设计的程序。
我们这个小组所做的实验是仿真一个数字时钟,通过DS1302这个芯片从计算机上读取时间信息,再由51单片机对数据进行处理、分配,将其输出在LCD1602上,实现简单的数字时钟的功能。
设计内容及要求:(1)根据设计课题的技术指标和给定条件,在教师指导下,能够独立而正确地进行方案论证和设计计算,要求概念清楚、方案合理、方法正确、步骤完整;(2)要求学生掌握单片机的设计内容、方法和步骤;(3)要求会查阅有关参考资料和手册等;(4)要求学会选择有关元件和参数;(5)要求学会绘制有关电路图和设计流程图;(6)要求学会编写设计说明书。
系统框图:硬件选择:1、AT89C51AT89C51是一种带4K字节FLASH存储器(FPEROM—Flash Programmable and Erasable Read Only Memory)的低电压、高性能CMOS 8位微处理器,俗称单片机。
AT89C2051是一种带2K字节闪存可编程可擦除只读存储器的单片机。
单片机的可擦除只读存储器可以反复擦除1000次。
该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,AT89C2051是它的一种精简版本。
AT89C51单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。
AT89C51外形及引脚排列主要特性:·与MCS-51 兼容·4K字节可编程FLASH存储器·寿命:1000写/擦循环·数据保留时间:10年·全静态工作:0Hz-24MHz·三级程序存储器锁定·128×8位内部RAM·32可编程I/O线·两个16位定时器/计数器·5个中断源·可编程串行通道·低功耗的闲置和掉电模式·片内振荡器和时钟电路特性概述:AT89C51 提供以下标准功能:4k 字节Flash 闪速存储器,128字节内部RAM,32 个I/O 口线,两个16位定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。
简析基于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个轻触开关,用于设定和修改时间项。
基于DS+LCD的数字万年历,具有按键可调功能基于DS1302+LCD1602的数字万年历,具有按键可调功能基于DS1302+LCD1602的数字万年历,具有按键可调功能主程序流程图:按键扫描过程中,用了三个键:key0(功能键)key1(增大键)key2(减小键)用变量num记录功能键按下次数switch(num){ case 1: flag=1;//修改时间,禁止液晶从DS1302读数据LCD_WRITE_COM(0x0f);//光标开始闪烁LCD_WRITE_COM(0x80+3);//第一次按下,光标定位到年位置break;case 2: LCD_WRITE_COM(0x80+6);//第二次按下,光标定位到月位置break;case 3: LCD_WRITE_COM(0x80+9);//第三次按下,光标定位到日位置break; case 4: LCD_WRITE_COM(0x80+12);//第四次按下,光标定位到星期位置break; case 5:LCD_WRITE_COM(0x80+0x40+4);//第五次按下,光标定位到时位置break;case 6: LCD_WRITE_COM(0x80+0x40+7);//第六次按下,光标定位到分位置break;case 7: LCD_WRITE_COM(0x80+0x40+10);//第七次按下,光标定位到秒位置break;case 8: num=0;//第八次按下,记录清零LCD_WRITE_COM(0x0c);//不显示光标WRITE_1302(WRITE_PROTECT,0x00);//禁止写保护WRITE_1302(0x80,(second/10*16)+second%10);//将调节后的秒写入DS1302 WRITE_1302(0x82,(minute/10*16)+minute%10);//将调节后的分写入DS1302 WRITE_1302(0x84,(hour/10*16)+hour%10);//将调节后的时写入DS1302 WRITE_1302(0x8a,(week/10*16)+week%10);//将调节后的星期写入DS1302 WRITE_1302(0x86,(day/10*16)+day%10);//将调节后的日写入DS1302WRITE_1302(0x88,(month/10*16)+month%10);//将调节后的月写入DS1302WRITE_1302(0x8c,(year/10*16)+year%10);//将调节后的年写入DS1302WRITE_1302(WRITE_PROTECT,0x80);//开写保护flag=0;//时间修改完毕,允许液晶从DS1302读数据break;}仿真时的现象:。
学习情境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移动通信工具等众多领域。
数字开发与实践课程设计题目:用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时钟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应用,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【程序、仿真、完整】) 基于52单片机的万年历显示(采用实时芯片DS1302芯片+LCD1602液晶显示)仿真图:项目名称:Real_TimerLM016LLCD1VSSVDDVEERSRWEC122pF+5VC222pFD0D1D2D3D4D5D6D7RP11234567891 011121314+5VX11912MHzU1XTAL1P0.0/AD0P0.1/AD1P0.2/AD2P0.3/AD3P0.4/AD4P0.5/AD5P0 .6/AD6P0.7/AD7P2.0/A8P2.1/A9P2.2/A10P2.3/A11P2.4/A12P2.5/A13P2.6/A14P2.7/A15P3 .0/RXDP3.1/TXDP3.2/INT0P3.3/INT1P3.4/T0P3.5/T1P3.6/WRP3.7/RD393837363534333221 22232425262728101112131415161712345678910K+5V18XTAL2C320uF1k9RST+5V+5V1.5V1.5V 293031PSENALEEAAT89C52R1RV110kU22X1VCC1VCC281+5VX23X2RSTSCLKI/O57612345678P1.0 /T2P1.1/T2EXP1.2P1.3P1.4P1.5P1.6P1.732768DS1302说明:用ds1302和lcd1602显示实时时钟 x x x x x x 程序: LCD1602的H文件:/************************************************************ -- THE LCD1602 DISPLAY LIB --COPYRIGHT (C) 2021 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) 2021 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; sbitACC0=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]; uchartime_str[9]; }date_time;/**************写数据定义*****************/ #define DS1302_SECOND 0x80#define DS1302_MINUTE 0x82 #define DS1302_HOUR 0x84 #define DS1302_WEEK0x8A #define DS1302_DAY 0x86 #define DS1302_MONTH 0x88 #define DS1302_YEAR 0x8C #define ST 0x00/*************单字节写数据子程序**************/ voidsingle_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(ucharaddr,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); //写入当前时间数据 } }感谢您的阅读,祝您生活愉快。
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显示电子表》成员姓名:*** 学号:******成员姓名: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(); ﻩﻩ //扫描各功能键ﻩﻩ}}}。
中州大学信息工程学院毕业设计(论文)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周:熟悉课题的基本要求,查阅相关资料,初步拟定设计的整体方案,完成开题报告。
实验总成绩: __________报告份数:1份西安邮电大学通信与信息工程学院课程设计实验报告专业班级:_________________学生姓名:__________________________学号(班内序号): ____________ 年—月—日成绩鉴定表、设计任务和目的1.用单片机设计基于STC89C52, DS1302, LCD 1602的电子钟,显示时间和日期2.具有时间和日期的校准,记忆功能3.搭建仿真电路,模拟要实现的功能4.焊接单片机实物5.熟练掌握相关软件的使用方法,以及各个器件的基本工作原理6•编写程序,下载并调试,实现要求的功能二、设计思路和方案电路整体上分为控制和显示部分,以单片机最小系统为核心电路,控制LCD 显示,具体的显示内容和方式由软件来完成;由于有时钟和H期的调节功能需要校准电路和基本的复位电路,复位电路采用按键复位,调节键、加1键、减1键,共四键,计时功能由DS1302 完成,显示功能则由LCD 1602液晶完成三.基本设计原理该电子时钟是利用单片机内部的定时器\计数器来实现的,它的处理过程如下:首先设定单片机内部的一个定时器\计数器工作于定时方式,对机器周期计数形成基准时间,然后用另一个定时器\计数器或软件计数的方法对基准时间计数形成秒,秒计60次形成分,分计60次形成小时,小时计24次则计满一天。
然后通过LCD1602液晶把它们的内容在相应位置显示出来即可。
译码方式可分为软件译码和硬件译码,软件译码通过译码程序查得显示信息的字段码;硬件译码通过硬件译码器得到显示信息的字段码,实际中通常采用软件译码。
在具体处理时,定时器计数器采用中断方式工作,对时钟的形成在中断服务程序中实现。
在主程序中只需对定时器计数器初始化、调用显示子程序和控制子程序。
另外,为了使用方便,设计了简单的按键,可以通过按键实现时、分和H期的调整,这样在主程序中就加入了键盘设置子程序。
由于使用了时间记忆芯片DS1302故断电后下次通电时间能够保持不变,更加的合理人性化。
数字开发与实践课程设计题目:用DS1302与LCD1602设计可调式电子日历时钟班级:姓名:学号:学院:二O一二年六月五日用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所示图2-12.2、系统总体设计原理图2.3、要求用proteus仿真软件仿真并抓图。
三、软件设计3.1、画出各个函数流程图。
3.1.1、DS1302实时控制芯片的流程图如图3-1图3-13.1.2、LCD1602液晶显示控制流程图如图3-2是图3-2如图3-3图3-33.2、写出程序代码。
/**************DS1302及1602时钟设计**********/ #include <reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned int#define SECOND 0x81#define MINUTE 0x83#define HOUR 0x85sbit rs=P2^0;sbit rw=P2^1;sbit ep=P2^2;sbit DS1302_IO= P1^0;sbit DS1302_SCLK = P1^1;sbit DS1302_RST = P1^2;sbit M=P3^1; //选择sbit U=P3^2; // 加sbit D=P3^3; // 减sbit W=P3^4; //确定sbit SPK=P3^7; //蜂鸣器uchar sel=0;uchar code DIS1[]={"10 ji ying "};uchar code DIS2[]={"ke cheng she ji"};/////////////////////////延时////////////////////////////////void delay(uint ms){unsigned int a,b;for(a=0;a<ms;a++)for(b=0;b<124;b++);}/////////////////////////////////////////////////////////////***************DS1302驱动************************/////////////////////////////////////////////////////////////void DS1302_Write(uchar D){uchar i;for(i=0;i<8;i++){DS1302_IO =D&0x01;DS1302_SCLK=1;DS1302_SCLK=0;D=D>>1;}}uchar DS1302_Read(){uchar TempDat=0,i;for(i=0;i<8;i++){ TempDat>>=1;if(DS1302_IO) TempDat=TempDat|0x80;DS1302_SCLK=1;DS1302_SCLK=0;}return TempDat;}void WDS1302(uchar ucAddr, uchar ucDat){DS1302_RST = 0;DS1302_SCLK = 0;DS1302_RST = 1;DS1302_Write(ucAddr);DS1302_Write(ucDat);DS1302_SCLK = 1;DS1302_RST = 0;}uchar RDS1302(uchar ucAddr){uchar ucDat;DS1302_RST = 0;DS1302_SCLK = 0;DS1302_RST = 1;DS1302_Write(ucAddr);ucDat=DS1302_Read();DS1302_SCLK = 1;DS1302_RST = 0;return ucDat;}/////////////////DS1302的初始状态的时间设定///////////////////// void init_1302(){WDS1302(0x8e,0x00);//开保护寄存器WDS1302(0x80,0x50);//秒WDS1302(0x82,0x01);//分WDS1302(0x84,0x14);//时WDS1302(0x8A,0x03);//星期WDS1302(0x86,0x06);//日WDS1302(0x88,0x06);//月WDS1302(0x8C,0x12);//年WDS1302(0x90,0xab);//卷电流充电WDS1302(0x8e,0x80);//关保护寄存器}/************************1602驱动************************/ bit lcd_bz(){bit result;rs = 0;rw = 1;ep = 1;_nop_();_nop_();_nop_();_nop_();result = (bit)(P0 & 0x80);ep = 0;return result;}////////////////////////////////////////////////////////void lcd_wcmd(uchar cmd){while(lcd_bz());rs = 0;rw = 0;ep = 0;_nop_();_nop_();P0 = cmd;_nop_();_nop_();_nop_();_nop_();ep = 1;_nop_();_nop_();_nop_();_nop_();ep= 0;}/////////////////////////////////////////////////////////void lcd_pos(unsigned char pos){lcd_wcmd(pos | 0x80);}/////////////////////////////////////////////////////////void lcd_wdat(unsigned char dat){while(lcd_bz());rs = 1;rw = 0;ep = 0;P0 = dat;_nop_();_nop_();_nop_();_nop_();ep = 1;_nop_();_nop_();_nop_();_nop_();ep = 0;}//////////////////////////////////////////////////////////void lcd_init(){lcd_wcmd(0x38);delay(1);lcd_wcmd(0x0c);delay(1);lcd_wcmd(0x06);delay(1);lcd_wcmd(0x01);delay(1);}//////////////////////////////////////////////////////////*********************调时函数*************************//////////////////////////////////////////////////////////void set_time(){signed char address,item;signed char max,mini;if(M==0){sel++;delay(300);//if(sel==7) sel=0;if(sel==2) {address=0x82; max=59;mini=0; } //分if(sel==1) {address=0x84; max=23;mini=0; } //时if(sel==6) {address=0x8c; max=99;mini=9;} //年if(sel==4) {address=0x88; max=12;mini=1; } //月if(sel==5) {address=0x86; max=31;mini=1; } //日if(sel==3) {address=0x8A; max=07;mini=1;} //星期M=1;}item=((RDS1302(address+1))/16)*10 + (RDS1302(address+1))%16;if(U == 0){delay(200);U=1;item++;}if(D == 0){delay(200);D=1;item--;}if(W == 0){delay(200);sel=0;W=1;}if(item>max) item=mini;if(item<mini) item=max;WDS1302(0x8e,0x00);//允许写操作WDS1302(address,(item/10)*16+item%10); //写入DS1302 //转成BCD码WDS1302(0x8e,0x80);//写保护,禁止写操作}//////////////////////////////////////////////////////////*********************显示子函数************************/ /////////////////////////////////////////////////////////void lcdshow_u(uchar i,uchar y){lcd_wcmd(0x80+i);lcd_wdat(y);}void lcdshow_d(uchar i,uchar y){lcd_wcmd(0xC0+i);lcd_wdat(y);}/*******************显示函数****************************/ void display(void){uchar x,y;x=RDS1302(HOUR);//时y=x;x=x>>4; lcdshow_u(6,0x30+x);y=y&0x0f; lcdshow_u(7,0x30+y);lcdshow_u(8,':');x=RDS1302(MINUTE);//分y=x;x=x>>4; lcdshow_u(9,0x30+x);y=y&0x0f; lcdshow_u(0x0a,0x30+y);lcdshow_u(0x0b,':');x=RDS1302(SECOND);//秒y=x;x=x>>4; lcdshow_u(0x0c,0x30+x);y=y&0x0f; lcdshow_u(0x0d,0x30+y);x=RDS1302(0x8b);y=x;x=x>>4; lcdshow_u(0x0e,0x30+x);y=y&0x0f; lcdshow_u(0x0f,0x30+y);x=RDS1302(0x8d);y=x;x=x>>4; lcdshow_d(8,0x30+x);y=y&0x0f; lcdshow_d(9,0x30+y);lcdshow_d(0x0a,'-');x=RDS1302(0x89);y=x;x=x>>4; lcdshow_d(0x0b,0x30+x);y=y&0x0f; lcdshow_d(0x0c,0x30+y);lcdshow_d(0x0d,'-');x=RDS1302(0x87);y=x;x=x>>4; lcdshow_d(0x0e,0x30+x);y=y&0x0f; lcdshow_d(0x0f,0x30+y);/////////////////////下面的if实现每到8:10和14:10的提醒功能/////////////////////////////////if((RDS1302(HOUR)==0x14 & RDS1302(MINUTE)==0x10)| ( RDS1302(HOUR)==0x08 & RDS1302(MINUTE)==0x10)){SPK = 0;delay(200);SPK = 1;}for(x=45;x>0;x--){set_time();delay(10);}}/**************************主函数******************************/ void main(){uchar i;lcd_init();delay(10);lcd_pos(0x03);i = 0;while(DIS1[i] != '\0'){lcd_wdat(DIS1[i]);i++;}lcd_pos(0x41);i = 0;while(DIS2[i] != '\0'){lcd_wdat(DIS2[i]);delay(200);i++;}init_1302();delay(1000);for(i=0;i<17;i++){lcdshow_u(i,'>');delay(150) ;}for(i=0;i<17;i++){lcdshow_d(i,'<');delay(150) ;}lcd_init();delay(10);lcdshow_u(0,'T');lcdshow_u(1,'i');lcdshow_u(2,'m');lcdshow_u(3,'e');lcdshow_u(14,' ');lcdshow_d(0,'D');lcdshow_d(1,'a');lcdshow_d(2,'t');lcdshow_d(3,'a');lcdshow_d(6,'2');lcdshow_d(7,'0'); //LCD框架描绘while(1){set_time();if(sel==2){lcdshow_u(0X09,' ');lcdshow_u(0x0a,' ');delay(500); }if(sel==1){lcdshow_u(0X06, ' ');lcdshow_u(0X07,'if(sel==3) {lcdshow_u(0X0E,' ');lcdshow_u(0X0F,' ');delay(500); }if(sel==4){lcdshow_d(0x0b,' ');lcdshow_d(0x0c,' ');delay(500); }if(sel==5){lcdshow_d(0x0e,' ');lcdshow_d(0x0f,' ');delay(500); }if(sel==6) {lcdshow_d(0x08,' ');lcdshow_d(0x09,' ');delay(500); }if(sel==8) display();//调时LCD闪烁显示display();}}四、专业实习要求1、掌握常用设备的使用;2、掌握keil 编译环境的使用,熟悉proteus仿真软件的使用;3、基本掌握电路板的焊接调试技巧;4、基本掌握51单片机最小应用系统的组装、调试。