介绍DS1302时钟芯片的电路和程序

电子说

1.3w人已加入

描述

DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,并且具有闰年补偿等多种功能。

1、参考电路

如下参考电路已经过实践验证,可正常工作。

ACC

其中,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()子程序不能每次开机运行,只需在修改时间时运行即可。

以上电路和程序已经过实践验证,可正常运行。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分