本文介紹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文章
245瀏覽量
65781 -
微處理器
+關注
關注
11文章
2263瀏覽量
82445 -
DS1302
+關注
關注
8文章
449瀏覽量
50689 -
電流充電器
+關注
關注
0文章
8瀏覽量
6002 -
紐扣電池
+關注
關注
2文章
112瀏覽量
7618
發布評論請先 登錄
相關推薦
評論