基于DS1302和AT89C51的万年历制作一、题目分析以及器件选择1、设计要求:电子万年历(a>、基本功能要求:1>能够正确进行日历记录和显示2>能够输入设定年份3>能够通过按键进行日历的调整4>能够测试出温度2、方案选择:1>时钟芯片的选择在这个系统中,最重要的就是时钟芯片的选择,在电子时钟设计中,常用的时钟芯片有DS1302、DS1216、DS1643、DS1302。
每种芯片的主要功能基本相同,只是在引脚数量、备用电池的安装方式、计时精度和扩展功能等方面略有不同。
DS12877与DS1216芯片都有内嵌式锂电池作为备用电源:X1203引脚少,没有嵌入式锂电池,跟DS1302芯片功能相似,只是相比较之下,X1203与AT89S51搭配使用时占用I/O口较多。
DS1643为带有全功能实时时钟的非易失性型SRAM,集成了非易失性型SRAM、实时时钟、晶振、电源掉电控制电路和锂电池电源,BCD码表示的年、月、日、星期、时、分、秒,带闰年补偿。
同样。
DS1643拥有28只管脚,硬件连起来占用微处理器I/O口较多,不方便系统功能拓展和维护。
故而从性价比和货源上考虑,本设计采用实时时钟芯片DS1302。
2>显示器件的选择显示器件的选择范围很广,成本最低的就是采用八位数码管进行显示,但是使用八位数码管,经过评估和计算需要至少八个,这占用了太大的空间,而且很不美观。
第二个选择就是使用液晶,采用12864大液晶是普遍的选择,但是成本太高,而且函数调用不便,程序较长,因此从节约成本的角度考虑,使用小液晶1602进行设计。
3>设计评估本次设计完成了基本要求规定那个的所有内容,能够正确进行日历记录和显示、能够输入设定年份、能够通过按键进行日历的调整、能够进行整点报时、每年1月1日进行新年报时。
二、DS1302简介1、总体概述图一:DS1302外部引脚DS1302是一种高性能、低功耗的实时时钟芯片,附加有31字节静态RAM,采用SPI 三线接口与CPU进行同步通信,并可以采用突发方式,一次传送多个字节的时钟信号或RAM数据。
实时时钟可以提供秒、分、时、日、星期、月和年,一个月小于31日时可以自动调整,包括闰年,有效值2100年。
可以采用12h或24h方式计时,采用双电源供电,可设置备用电源充电方式,同时提供了对后备电源进行涓流充电的能力。
7个附加字节的暂存储器,包括移位寄存器、控制逻辑、振荡器、实时时钟和RAM。
芯片为8引脚小型DIP表一:DS1302引脚功能说明2、DS1302的控制字和读写时序说明在变成过程中要注意DS1302的读写时序。
DS1302是SPI总线驱动方式。
它不仅要向寄存器写入控制字,还需要读取相应寄存器的数据。
要想与DS1302通信,首先要了解DS1302控制字的作用是设定DS1302的工作方式、传输字节等。
每次数据的传输都是由控制字开始。
控制字各位的含义和作用如下:1、BIT7:控制字的最高位有效,必须是逻辑1,如果它为0,则不能把数据写入到DS1302中;2、BIT6:如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;3、BIT5至BIT1<A4~A0):用A4~A0表示,定义片内寄存器和RAM地址。
定义如下:当BIT6位=0时,定义时钟和其他寄存器的地址。
A4~A0=0~6,顺序为妙、分、时、日、月、星期、年的寄存器。
当A4~A0=7,为芯片写保护寄存器地址。
当A4~A0=8.为慢速充电参数选择寄存器。
当A4~A0=31,为时钟多字节方式选择寄存器。
当BIT6=1时,定义RAM的地址,A4!A0=0~30,对应各子地址的RAM,地址31对应的是RAM多字节方式选择寄存器。
4、BIT0<最低有效位):如果为0,表示要进行写操作,为1表示进行读操作。
控制字总是从最低位开始输出。
在控制字指令输入后的下一个SCLK时钟上升沿时,数据被写入DS1302,数据输入从最低位<0位)开始。
同样,在紧跟8位的控制字指令后的下一个SCLK脉冲的下降沿,读出DS1302的数据,读出的数据也是从最低位到最高位。
图二:DS1302数据读写时序三、DS1302在单片机系统中应用的实现DS1302与单片机的链接仅需要3条线,即SCLK、I/O、RST。
VCC2在单电源与电池供电的系统中提供地电源并能提供低功率的电池备份。
VCC2在双电源系统中提供电源,在这种运行方式下VCC1连接到备份电源,以便在没有主电源的情况下能保存时间信息以及数据。
DS1302由两者中的较大者供电。
当VCC2大于VCC1+0.2V时,VC2给DS1302供电。
当VCC2小于在单片机系统中使用VCC1的时候,DS1302由VCC1供电。
在本系统中,以ATmega为主器件,DS1302为从器件,RST接在主器件的PC4/TD0上,此引脚为高位的时候,选中该芯片,对其进行操作。
串行数据线I/O与串行时钟线SCLK分别接在PC3/TMS和PC2/TCK上,所有的单片机地址、命令、及数据均通过这两条线传输。
在系统中,主器件在总线上产生时钟脉冲,寻址信号,数据信号,而从器件则相应接收数据,送出数据。
对DS1302的每一次读写都需要16个时钟脉冲,前8个脉冲输入操作地址和读写命令。
1、硬件设计此系统中的主要器件为单片机AT89C51和DS1302,系统的逻辑图如下:图三:系统的逻辑框图其接口电路如图四所示。
图四:接口电路2、程序设计单片机控制DS1302时钟芯片的程序,主要包括两个方面的关键内容,一个是单片机对DS1302寄存器的地址定义和控制字的写入,二是数据的读取。
单片机控制的DS1320时钟实时时间控制楼成图如下:为了节约成本,使用了实验室的开发板进行连接,只是外接了一个1602小液晶。
电路图在整体框架图中可以看见。
四、总结串行时钟芯片DS1302连线简单、体积小、价格低,再为控制其系统中应用有着突出的优点。
DS1302可以用于数据记录,特别是对某些具有特殊意义的数据点的记录,能实现数据与出现该数据的时间同时记录。
这种记录对长时间的连续测控系统结果分析及对异常数据出现的原因的查找具有重要意义。
附录一:主程序#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。
char hide_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液晶显示部分子程序****************///Port Definitions**********************************************************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>。