本文介绍DS1302时钟芯片的电路和程序。
DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,并且具有闰年补偿等多种功能。
1、参考电路
如下参考电路已经过实践验证,可正常工作。
其中,PU151到PU153对应DS1302的SCLK,IO,RST引脚,需接到微处理器(如单片机)的相关引脚。
第8脚加上3V的后备纽扣电池,时钟在主电路掉电时也可以持续运行。
2、参考程序
实践验证,以下两个程序任意一个都是可以运行的。
2.1参考程序1
//DS1302设置子程序
#include "ds1302.h"
sbit sclk=P3^3;//DS1302设置
sbit rst=P3^5;
sbit io=P3^4; //DS1302三个管脚定义
unsigned char xdata time[7]={23,1,3,20,5,6,7};//0年 1周 2月 3日 4时 5分 6秒 有符号
unsigned char write_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};//DS1302写时间寄存器地址
unsigned char read_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};//读
void write_ds1302_byte(unsigned char dat) //DS1302写字节函数
{
unsigned char i;
for(i=0;i<8;i++)
{
sclk=0; //下降沿数据有效
io=dat&0x01;
dat=dat>>1;
sclk=1;
}
}
void write_ds1302(unsigned char add,unsigned char dat)
{
rst=0;
nop ();
sclk=0;
nop ();
rst=1;
nop ();
write_ds1302_byte(add);
write_ds1302_byte(dat);//发送地址后立即发送数据,没有停顿
rst=0;
nop ();
sclk=1;
io=1;
}
unsigned char read_ds1302(unsigned char add)
{
unsigned char i,dat=0;
rst=0;
nop ();
sclk=0;
nop ();
rst=1;
nop ();
write_ds1302_byte(add);//发送地址后DS1302立即送出数据
for(i=0;i<8;i++)
{
dat=dat>>1;
sclk=0;
if(io)
dat=dat|0x80;
sclk=1;
}
rst=0;
nop ();
sclk=0;
nop ();
sclk=1;
io=0; //223-3-20,1改为0后可保存数据
return dat;
}
void ds1302_init()
{
unsigned char i,j;
for(i=0;i<7;i++)
{
j=time[i]/10;
time[i]=time[i]%10;
time[i]=time[i]+j*16; //转换为BCD码
}
write_ds1302(0x8e,0x00);//去除写保护
for(i=0;i<7;i++)
{
write_ds1302(write_add[i],time[i]);
}
write_ds1302(0x8e,0x80);//加写保护
}
void read_time()//读时间
{
unsigned char i;
for(i=0;i<8;i++)
{
time[i]=read_ds1302(read_add[i]);
time[i]=time[i]/16*10+time[i]%16;//转换BCD码为十进制
}
if (time[4]>23) time[4]=23;
if (time[5]>59) time[5]=59;
if (time[6]>59) time[6]=59;
}
说明:
●如果要读取时间,就调用read_time()子程序,读取的时钟数据存入time[]数组;
●如果要设置时间,就调用ds1302_init()子程序,要设置的时钟数据预先存入time[]数组;
●ds1302_init()子程序不能每次开机运行,只需在修改时间时运行即可。
2.2参考程序2
#include "DS1302.h"
#define uchar unsigned char
#define uint unsigned int
//DS1302宏定义部分
#define WRITE_SECOND 0x80 //写秒地址
#define WRITE_MINUTE 0x82 //写分地址
#define WRITE_HOUR 0x84 //写时地址
#define WRITE_DATE 0x86 //写日地址
#define WRITE_MONTH 0x88 //写月地址
#define WRITE_WEEK 0x8A //写周地址
#define WRITE_YEAR 0x8C //写年地址
#define WRITE_PROTECT 0x8E //写保护
#define READ_SECOND 0x81 //读秒地址
#define READ_MINUTE 0x83 //读分地址
#define READ_HOUR 0x85 //读时地址
#define READ_DATE 0x87 //读日地址
#define READ_MONTH 0x89 //读月地址
#define READ_WEEK 0x8B //读周地址
#define READ_YEAR 0x8D //读年地址
sbit ACC_7 = ACC^7; //位寻址寄存器定义
sbit SCLK = P3^3; // DS1302时钟信号6脚
sbit DIO= P3^4; // DS1302数据信号5脚
sbit CE = P3^5; // DS1302片选7脚
uchar xdata time[7]={23,1,3,2,5,6,7}; //依次存放年月日周时分秒,十进制表示,2023年1月3日周2 5:6:7
//地址、数据发送子程序
void Write1302 ( unsigned char addr,dat )
{
unsigned char i,temp;
CE=0; //CE 引脚为低,数据传送中止
SCLK=0; //清零时钟总线
CE = 1; //CE 引脚为高,逻辑控制有效
//发送地址
for ( i=8; i >0; i-- ) //循环8次移位
{
SCLK = 0;
temp = addr;
DIO = (bit)(temp&0x01); //每次传输低字节
addr > >= 1; //右移一位
SCLK = 1;
}
//发送数据
for ( i=8; i >0; i-- )
{
SCLK = 0;
temp = dat;
DIO = (bit)(temp&0x01); //每次传输低字节
dat > >= 1; //右移一位
SCLK = 1;
}
CE = 0;
}
//数据读取子程序
unsigned char Read1302 ( unsigned char addr )
{
unsigned char i,temp,dat1,dat2;
CE=0;
SCLK=0;
CE = 1;
//发送地址
for ( i=8; i >0; i-- ) //循环8次移位
{
SCLK = 0;
temp = addr;
DIO = (bit)(temp&0x01); //每次传输低字节
addr > >= 1; //右移一位
SCLK = 1;
}
//读取数据
for ( i=8; i >0; i-- )
{
ACC_7=DIO;
SCLK = 1;
ACC >>=1;
SCLK = 0;
}
CE=0;
dat1=ACC;
dat2=dat1/16; //数据进制转换
dat1=dat1%16; //十六进制转十进制
dat1=dat1+dat2*10;
return (dat1);
}
//初始化 DS1302
void InitialDS1302(void)
{
//初始化为13年04月24日周3 23时27分56秒 注意,Write1302函数第二个参数是16进制,需进行十进制到十六进制转码,如参数里:秒0X56表示56秒,0X12表示12月,0x23表示23时等,以下已转码。
Write1302 (WRITE_PROTECT,0X00); //禁止写保护
Write1302 (WRITE_SECOND,time[6]/10*16+time[6]%10); //秒位初始化
Write1302 (WRITE_MINUTE,time[5]/10*16+time[5]%10); //分钟初始化
Write1302 (WRITE_HOUR,time[4]/10*16+time[4]%10); //时位初始化
Write1302 (WRITE_YEAR,time[0]/10*16+time[0]%10); //年位初始化
Write1302 (WRITE_MONTH,time[1]/10*16+time[1]%10); //月位初始化
Write1302 (WRITE_DATE,time[2]/10*16+time[2]%10); //日位初始化
Write1302 (WRITE_WEEK,time[3]/10*16+time[3]%10); //星期位初始化
Write1302 (WRITE_PROTECT,0x80); //允许写保护
}
//读取年月日周时分秒
void read_time(void)
{
time[0]=Read1302(READ_YEAR); //取年
time[1]=Read1302(READ_MONTH); //取月
time[2]=Read1302(READ_DATE); //取日
time[3]=Read1302(READ_WEEK); //取周
time[4]=Read1302(READ_HOUR); //取时
time[5]=Read1302(READ_MINUTE); //取分
time[6]=Read1302(READ_SECOND); //取
}
//// 运行 read_nyrsfm()子函数读取数组time[]显示即可
说明:
●如果要读取时间,就调用read_time()子程序,读取的时钟数据存入time[]数组;
●如果要设置时间,就调用InitialDS1302()子程序,要设置的时钟数据预先存入time[]数组。
●InitialDS1302()子程序不能每次开机运行,只需在修改时间时运行即可。
以上电路和程序已经过实践验证,可正常运行。
-
实时时钟
+关注
关注
4文章
237浏览量
65666 -
微处理器
+关注
关注
11文章
2246浏览量
82283 -
DS1302
+关注
关注
8文章
449浏览量
50593 -
电流充电器
+关注
关注
0文章
8浏览量
5996 -
纽扣电池
+关注
关注
2文章
111浏览量
7589
发布评论请先 登录
相关推荐
评论