芯片简介

DS1302是DALLAS公司推出的涓流充电时钟芯片,内含一个实时时钟/日历和31字节静态RAM,可以通过串行接口与单片机进行通信。实时时钟/日历电路提供秒、分、时、日、星期、月、年的信息,每个月的天数和闰年的天数可自动调整,时钟操作可通过AM/PM标志位决定采用24或12小时时间格式。

DS1302与单片机之间能简单地采用同步串行的方式进行通信,仅需三根I/O线:复位(RST)、I/O数据线、串行时钟(SCLK)。时钟/RAM的读/写数据以一字节或多达31字节的字符组方式通信。DS1302工作时功耗很低,保持数据和时钟信息时,功耗小于1mW。
在这里插入图片描述

X1,X2:外界晶振
RST:复位
I/O:数据输入/输出
SCLK:时钟线

寄存器介绍

在这里插入图片描述
注意:
(1)DS1302采用的BCD码,写入和读出时需要进行转化!
(2)CH为时钟暂停标志,置0时钟开始计时
(3)WP为写保护位,置0时才可以写入数据

在这里插入图片描述

此为DS1302的控制字节,上面那些寄存器的地址就是按这个格式来的

DS1302的读写时序

写:
在这里插入图片描述

每一次写需要两个字节:地址+数据
单字节写的时序:
先得将CE(也可说是RST)置高电平,然后单片机数据放到I/O上,当I/O的数据稳定后,将SCLK置高电平,DS1302检测到SCLK的上升沿后就将I/O上的数据读取,然后单片机将SCLK置为低电平,如此反复,当传完数据后,单片机将CE置为低电平,操作结束。

//写一个字节
void Write_Ds1302(unsigned  char temp) 
{
	unsigned char i;
	for (i=0;i<8;i++)     	
	{ 
		SCK=0;
		SDA=temp&0x01;
		temp>>=1; 		//从低位开始写
		SCK=1;
	}
}  
// 写入一个字节的数据
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )     
{
 	RST=0;	
 	_nop_();
 	SCK=0;	
 	_nop_();
 	RST=1; 	
 	_nop_();  
 	Write_Ds1302(address);	
 	Write_Ds1302(dat);		
 	RST=0; 
}

读:
在这里插入图片描述
每一次读数据也需要两个字节:地址+读到的数据
写的话同上,这里注意读数据时:DS1302在SCLK为高电平期间将数据放到I/O口上,然后在下降沿数据读取数据。

//读取一个字节的数据
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
 	unsigned char i,temp=0x00;
 	RST=0;	
 	_nop_();
 	SCK=0;	
 	_nop_();
 	RST=1;	
 	_nop_();
 	Write_Ds1302(address);
 	for (i=0;i<8;i++) 	
 	{		
		SCK=0;
		temp>>=1;		//从低位开始读
 		if(SDA)
 		temp|=0x80;	
 		SCK=1;
	} 
 	RST=0;	
 	_nop_();
 	SCK=0;	
 	_nop_();
	SCK=1;	
	_nop_();
	SDA=0;	
	_nop_();
	SDA=1;	
	_nop_();
	return (temp);			
}

DS1302的操作方法:
写入:
(1)将写保护位WP置0
(2)将时间数据转成BCD码写入寄存器
(3)将写保护位置1

(1)将数据从寄存器读出
(2)转成16进制
(3)连续操作时加延时!(我去,不加延时也可以了……惊了)

//将初始时间写入芯片
void WriteTime_DS1302()
{
	Write_Ds1302_Byte(0x8e,0x00);
	Write_Ds1302_Byte(0x84,((hour/10)<<4)|(hour%10));
	Write_Ds1302_Byte(0x82,((minute/10)<<4)|(minute%10));
	Write_Ds1302_Byte(0x80,((second/10)<<4)|(second%10));
	Write_Ds1302_Byte(0x8e,0x80);
}

//读取时间
void ReadTime_DS1302()
{
	hour=Read_Ds1302_Byte(0x85);
	minute=Read_Ds1302_Byte(0x83);
	second=Read_Ds1302_Byte(0x81);
	
	hour=(hour>>4)*10+(hour&0x0f);
	minute=(minute>>4)*10+(minute&0x0f);
	second=(second>>4)*10+(second&0x0f);
}

Reference:
http://www.elecfans.com/monijishu/jiekou_shizhong_PLL/567072.html