现在流行的串行时钟电路很多,如DS1302、 DS1307、PCF8485等。这些电路的接口简单、价格低廉、使用方便,被广泛地采用。
DS1302 是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.0V~5.5V。采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后备电源双电源引脚,同时提供了对后备电源进行涓细电流充电的能力,该芯片采用普通32.768kHz晶振,DS1302 工作时功耗很低保持数据和时钟信息时功率小于1mW。
图1 DS1302时钟模块实物图
图2 DS1302时钟模块封装
表1 DS1302芯片引脚功能介绍表
VCC1 |
后备电源 |
GND |
电源地 |
VCC2 |
工作电源 |
X1 |
晶振32.768kHz输入 |
X2 |
|
SCLK |
时钟信号 |
I/O |
数据输入输出 |
RST |
复位信号|片选信号 |
DS1302时钟模块的引脚功能介绍如表1所示,而时序不再做陈述,需要再自行查找资料。
#ifndef _DS1302_H_
#define _DS1302_H_
#include "STC15F2K60S2.h"
#ifndef UINT8
#define UINT8 unsigned char
#endif
#ifndef DS1302_READ_BURST
#define DS1302_READ_BURST 0xBF
#endif
#ifndef DS1302_WRITE_BURST
#define DS1302_WRITE_BURST 0xBE
#endif
sbit DS1302_IO = P1^4;
sbit DS1302_RST = P1^5;
sbit DS1302_SCLK = P1^3;
extern UINT8 xdata time[9];
extern UINT8 xdata date[11];
extern UINT8 xdata current_day[2];
//声明全局变量
void DS1302_WriteByte(UINT8 data_byte);//向ds1302写一个字节
void DS1302_ReadByte(UINT8 *data_byte);//从ds1302读一个字节
void DS1302_Start();//操作起始信号
void DS1302_Over();//操作结束信号
void DS1302_ClearWriteProtection();//清除写保护
void DS1302_SetWriteProtection();//设置写保护
void DS1302_SetTime(UINT8 *ds1302_set_buffer);//设置ds1302的时间
void DS1302_ReadTime(UINT8 *ds1302_build_buffer);//读取ds1302的时间
void Time_Build();//系统从ds1302读取时间
void Time_Set();//系统向ds1302设置时间
void Time_Init();//系统时间初始化
#endif
#include "ds1302.h"
void DS1302_WriteByte(UINT8 data_byte)//向ds1302写一个字节
{
UINT8 i;
for (i=0;i<8;i++)
{
DS1302_IO = data_byte & 0x01;
DS1302_SCLK = 1;
data_byte >>= 1;
DS1302_SCLK = 0;
}
}
void DS1302_ReadByte(UINT8 *data_byte) //从ds1302读一个字节
{
UINT8 i;
for (i=0;i<8;i++)
{
*data_byte >>= 1;
if (DS1302_IO){*data_byte |= 0x80;}
DS1302_SCLK = 1;
DS1302_SCLK = 0;
}
}
void DS1302_Start()//操作起始信号
{
DS1302_RST = 0;
DS1302_SCLK = 0;
DS1302_RST = 1;
}
void DS1302_Over()//操作结束信号
{
DS1302_IO = 0;
DS1302_RST = 0;
}
void DS1302_ClearWriteProtection()//清除写保护
{
DS1302_Start();
DS1302_WriteByte(0x8E);
DS1302_WriteByte(0x00);
DS1302_Over();
}
void DS1302_SetWriteProtection()//设置写保护
{
DS1302_Start();
DS1302_WriteByte(0x8E);
DS1302_WriteByte(0x80);
DS1302_Over();
}
void DS1302_SetTime(UINT8 *ds1302_set_buffer)//突发模式下设置时间
{
UINT8 i;
DS1302_ClearWriteProtection();
DS1302_Start();
DS1302_WriteByte(DS1302_WRITE_BURST);
for (i=0; i<7; i++)
{
DS1302_WriteByte(ds1302_set_buffer[i]);
}
DS1302_WriteByte(0x80);//突发模式一次要写8个字节,第八个字节是写保护字节
DS1302_Over();
}
void DS1302_ReadTime(UINT8 *ds1302_read_buffer)//突发模式下读取时间
{
UINT8 i,Temp;
DS1302_ClearWriteProtection();
DS1302_Start();
DS1302_WriteByte(DS1302_READ_BURST);
for (i=0; i<7; i++)
{
DS1302_ReadByte(ds1302_read_buffer+i);
}
DS1302_ReadByte(&Temp);//突发模式一次读8个字节,最后一字节读出来没用
DS1302_Over();
DS1302_SetWriteProtection();
}
void Time_Build()//读取时间后转换成需要的格式
{
UINT8 xdata ds1302_build_buffer[7];
DS1302_ReadTime(ds1302_build_buffer);
time[7] = (ds1302_build_buffer[0]&0x0f)+'0';
time[6] = ((ds1302_build_buffer[0]&0x70)>>4)+'0';
time[4] = (ds1302_build_buffer[1]&0x0f)+'0';
time[3] = ((ds1302_build_buffer[1]&0x70)>>4)+'0';
time[1] = (ds1302_build_buffer[2]&0x0f)+'0';
time[0] = ((ds1302_build_buffer[2]&0x30)>>4)+'0';
date[9] = (ds1302_build_buffer[3]&0x0f)+'0';
date[8] = ((ds1302_build_buffer[3]&0x30)>>4)+'0';
date[6] = (ds1302_build_buffer[4]&0x0f)+'0';
date[5] = ((ds1302_build_buffer[4]&0x10)>>4)+'0';
date[3] = (ds1302_build_buffer[6]&0x0f)+'0';
date[2] = ((ds1302_build_buffer[6]&0xf0)>>4)+'0';
}
void Time_Set()//将时间转化为对应格式存入ds1302
{
UINT8 xdata ds1302_set_buffer[7];
ds1302_set_buffer[0] = time[7]-'0';
ds1302_set_buffer[0] |= ((time[6]-'0')&0x07)<<4;
ds1302_set_buffer[1] = time[4]-'0';
ds1302_set_buffer[1] |= ((time[3]-'0')&0x07)<<4;
ds1302_set_buffer[2] = time[1]-'0';
ds1302_set_buffer[2] |= ((time[0]-'0')&0x03)<<4;
ds1302_set_buffer[3] = date[9]-'0';
ds1302_set_buffer[3] |= ((date[8]-'0')&0x03)<<4;
ds1302_set_buffer[4] = date[6]-'0';
ds1302_set_buffer[4] |= ((date[5]-'0')&0x01)<<4;
ds1302_set_buffer[6] = date[3]-'0';
ds1302_set_buffer[6] |= ((date[2]-'0')&0x0f)<<4;
ds1302_set_buffer[5] = 0x01;
DS1302_SetTime(ds1302_set_buffer);
}
void Time_Init()//开机时间初始化
{
Time_Build();
current_day[0] = date[8];
current_day[1] = date[9];//保存当前日期,用于检测日期变化
}
uchar a=0,b=0,c=0,d=0,e=0,f=0;
/**********显示时间**********/
a = date[2]; //发送年数据
b = date[3];
c = date[5]; //发送月数据
d = date[6];
e = date[8]; //发送日数据
f = date[9];
write_txt("t0.txt="); //发送文本
write_COM(34); //双引号
write_COM(a);
write_COM(b);
write_COM(34);
write_END(); //结束符
write_txt("t1.txt="); //发送文本
write_COM(34); //双引号
write_COM(c);
write_COM(d);
write_COM(34);
write_END(); //结束符
write_txt("t2.txt="); //发送文本
write_COM(34); //双引号
write_COM(e);
write_COM(f);
write_COM(34);
write_END(); //结束符
a = time[0]; //发送时数据
b = time[1];
c = time[3]; //发送分钟数据
d = time[4];
e = time[6]; //发送秒钟数据
f = time[7];
write_txt("t3.txt="); //发送文本
write_COM(34); //双引号
write_COM(a);
write_COM(b);
write_COM(34);
write_END(); //结束符
write_txt("t4.txt="); //发送文本
write_COM(34); //双引号
write_COM(c);
write_COM(d);
write_COM(34);
write_END(); //结束符
write_txt("t5.txt="); //发送文本
write_COM(34); //双引号
write_COM(e);
write_COM(f);
write_COM(34);
write_END(); //结束符
write_txt("t9.txt="); //发送文本
write_COM(34);
if(week==1) //发送星期数据
write_txt("一");
if(week==2)
write_txt("二");
if(week==3)
write_txt("三");
if(week==4)
write_txt("四");
if(week==5)
write_txt("五");
if(week==6)
write_txt("六");
if(week==7)
write_txt("日");
write_COM(34);
write_END();