DS1302实时时钟芯片简介
DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,并且具有闰年补偿等多种功能。采用串行数据传输,采用32.768kHz晶振。
DS1302实时时钟芯片特点
1、DS1302 与单片机之间能简单地采用同步串行的方式进行通信,仅需用到三条线:1、RES 复位,2、I/O 数据线,3、SCLK。
2、DS1302工作时的功耗很低,保持数据和时钟信息时功率小于1mW。
3、实时时钟具有能计算2100 年之前的秒分时日日期星期月年的能力还有闰年调整的能力。
4、宽范围工作电压2.0~5.5V。
5、可选工业级温度范围-40℃+85℃。
6、双电源管用于主电源和备份电源供应。
7、备份电源管脚可由电池或大容量电容输入。
DS1302实时时钟芯片管脚描述
寄存器地址/定义
上表第一行的CH表示时钟暂停控制位,置1时表示时钟暂停(时钟振荡器暂停),DS1302进入漏电流小于100nA的低功耗备用模式。置0时表示时钟开始。
WP表示write protect(写保护),置1表示写操作无效。在任何对时钟或RAM的写操作以前,WP必须为0;当为1时,写保护位禁止任何寄存器的写操作。因此,在试图写器件之前应该清除WP位。
TCS用于控制涓流充电,一般不进行设置。
寄存器的其它内容在下文中进行介绍。
命令字
下图显示了命令字节,命令字节启动每一次数据传输。
第7位必须是1。如果为0,将禁用对DS1302的写入。
第6位如果是1,则读取或写入RAM数据;如果是0,则读取或写入CK时钟。
第1到5位是地址,即要操作的地址,秒的地址是从0开始。
第0位为1时是read,对地址进行读取;为0时是write,对地址进行写入。
例如:
10000001(0x81)表示对时钟操作、秒地址操作、读。
10000000(0x80)表示对时钟操作、秒地址操作、写。
10001001(0x89)表示对时钟操作、月地址操作、读。
10001000(0x88)表示对时钟操作、月地址操作、写。
这与上文寄存器中的读地址和写地址是对应的。
时序图与数据读写
DS1302实时时钟芯片寄存器的读写需要用到三个引脚:CE(使能端)、SCLK(时钟)和I/O(数据)。在时钟上升沿,I/O口的数据将会被写入,在时钟下降沿,时钟芯片的数据将会被读出。
单字节写步骤(Write)
单字节读步骤(Read)
BCD码
注意:DS1302寄存器中的数据不是以二进制进行存储的,而是以BCD码进行存储的。所以将数据从DS1302中读取出来后还需要转为十进制来显示。
一个DS1302实时时钟芯片的例程:
/***************ds1302时钟数码管显示*****************
*单片机型号:STC89C52RC
*开发环境:KEIL
*名称:ds1302时钟数码管显示
**********************************************************/
#include <reg52.h>
#define uchar unsigned char
#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 0x8C
#define DS1302_RAM(X) (0xC0+(X)*2) //用于计算 DS1302_RAM 地址的宏
typedef struct __SYSTEMTIME__
{
uchar Second;
uchar Minute;
uchar Hour;
uchar Week;
uchar Day;
uchar Month;
uchar Year;
uchar DateString[9];
uchar TimeString[9];
}SYSTEMTIME; //定义的时间类型
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,
0x5e,0x79,0x71,0xbf};
sbit DS1302_CLK=P2^1; //实时时钟时钟线引脚
sbit DS1302_IO=P2^0; //实时时钟数据线引脚
sbit DS1302_RST=P2^4; //实时时钟复位线引脚
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
sbit LE2=P2^7;
sbit LE1=P2^6;
void delay1()
{
int x,y;
for(x=1;x>0;x--)
for(y=110;y>0;y--);
}
void DS1302InputByte(unsigned char d) //实时时钟写入一字节
{
uchar i;
ACC=d;
for(i=8;i>0;i--)
{
DS1302_IO=ACC0; //相当于汇编中的 RRC
DS1302_CLK=1;
DS1302_CLK=0;
ACC=ACC>>1;
}
}
uchar DS1302OutputByte(void) //实时时钟读取一字节
{
uchar i;
for(i=8;i>0;i--)
{
ACC=ACC >>1; //相当于汇编中的 RRC
ACC7=DS1302_IO;
DS1302_CLK=1;
DS1302_CLK=0;
}
return(ACC);
}
void Write1302(uchar ucAddr, uchar ucDa)
//ucAddr: DS1302地址, ucData: 要写的数据
{
DS1302_RST=0;
DS1302_CLK=0;
DS1302_RST=1;
DS1302InputByte(ucAddr); //地址,命令
DS1302InputByte(ucDa); //写1Byte数据
DS1302_RST=0;
}
uchar Read1302(unsigned char ucAddr) //读取DS1302某地址的数据
{
uchar ucData;
DS1302_RST=0;
DS1302_CLK=0;
DS1302_RST=1;
DS1302InputByte(ucAddr|0x01); //地址,命令
ucData = DS1302OutputByte(); //读1Byte数据
DS1302_RST = 0;
return(ucData);
}
void DS1302_SetProtect(bit flag) //是否写保护
{
if(flag){Write1302(0x8E,0x10);}
else{Write1302(0x8E,0x00);}
}
void DS1302_SetTime(uchar Address, uchar Value) // 设置时间函数
{
DS1302_SetProtect(0);
Write1302(Address,((Value/10)<<4|(Value%10)));
}
void DS1302_GetTime(SYSTEMTIME *Time)
{
uchar 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)
{
Time->DateString[0]=Time->Year/10 ; //分离出个位和十位
Time->DateString[1]=Time->Year%10 ;
Time->DateString[2]='-';
Time->DateString[3]=Time->Month/10;
Time->DateString[4]=Time->Month%10 ;
Time->DateString[5]='-';
Time->DateString[6]=Time->Day/10 ;
Time->DateString[7]=Time->Day%10 ;
Time->DateString[8]='\0';
}
void TimeToStr(SYSTEMTIME *Time)
{
Time->TimeString[0]=Time->Hour/10 ;
Time->TimeString[1]=Time->Hour%10 ;
Time->TimeString[2]=':';
Time->TimeString[3]=Time->Minute/10 ;
Time->TimeString[4]=Time->Minute%10 ;
Time->TimeString[5]=':';
Time->TimeString[6]=Time->Second/10;
Time->TimeString[7]=Time->Second%10 ;
Time->DateString[8]='\0';
}
void Initial_DS1302(void)
{
uchar Second=Read1302(DS1302_SECOND);
if(Second&0x80)
DS1302_SetTime(DS1302_SECOND,0);
}
void display(uchar sw,uchar wan,uchar qian,uchar bai,uchar shi,uchar ge)
{
LE2=1;
P0=0xfe;
LE2=0;
P0=0;
LE1=1;
P0=sw;
LE1=0;
delay1();
LE2=1;
P0=0xfd;
LE2=0;
P0=0;
LE1=1;
P0=wan;
LE1=0;
delay1();
LE2=1;
P0=0xfb;
LE2=0;
P0=0;
LE1=1;
P0=qian;
LE1=0;
delay1();
LE2 = 1;
P0 = 0xf7;
LE2 = 0;
P0 = 0;
LE1 = 1;
P0 = bai;
LE1 = 0;
delay1();
LE2=1;
P0=0xef;
LE2=0;
P0=0;
LE1=1;
P0=shi;
LE1=0;
delay1();
LE2=1;
P0=0xdf;
LE2=0;
P0=0;
LE1=1;
P0=ge;
LE1=0;
delay1();
}
void main()
{
uchar t0,t1,t2,t3,t4,t5;
SYSTEMTIME CurrentTime;
Initial_DS1302();
DS1302_SetTime(DS1302_HOUR,9); //设置的时间是09:24:18
DS1302_SetTime(DS1302_MINUTE,24);
DS1302_SetTime(DS1302_SECOND,18);
while(1)
{
DS1302_GetTime(&CurrentTime);
DateToStr(&CurrentTime);
TimeToStr(&CurrentTime);
t0=CurrentTime.TimeString[0];
t1=CurrentTime.TimeString[1];
t2=CurrentTime.TimeString[3];
t3=CurrentTime.TimeString[4];
t4=CurrentTime.TimeString[6];
t5=CurrentTime.TimeString[7];
display(table[t0],table[t1],table[t2],table[t3],table[t4],table[t5]);
}
}