DS1302是一款由美國DALLAS Semiconductor公司(現(xiàn)已被Maxim Integrated公司收購)設(shè)計(jì)的高性能、低功耗的實(shí)時(shí)時(shí)鐘集成電路。這款芯片因其簡單易用的接口和豐富的功能,在嵌入式系統(tǒng)、消費(fèi)電子、工業(yè)控制等多個(gè)領(lǐng)域得到廣泛應(yīng)用。
原理圖
寄存器
寄存器的最低位是讀寫控制位,0 是寫,1是讀。
寄存器里的數(shù)據(jù)是BCD碼格式,得到十進(jìn)制可以進(jìn)行分離:data>>4分離出十位,data&0x0F****得到個(gè)位。
秒寄存器說明:
秒寄存器的位7定義為時(shí)鐘暫停位。當(dāng)此位設(shè)置為邏輯1時(shí), 時(shí)鐘振蕩器停止,DS1302被置入低功率的備份方式, 其電源消耗小于 100 納安(nanoamp)。 當(dāng)把此位寫成邏輯 0 時(shí), 時(shí)鐘將啟動(dòng)。
控制寄存器說明:
寫保護(hù)寄存器的位7是寫保護(hù)位。 開始 7 位(位 0-6) 置為零, 在讀操作時(shí)總是讀出零。 在對時(shí)鐘或RAM 進(jìn)行寫操作之前, 位 7 必須為零。 當(dāng)它為高電平時(shí), 寫保護(hù)位禁止對任何其它寄存器進(jìn)行寫操作。
小時(shí)寄存器說明:
小時(shí)寄存器的位 7 定義為 12 或 24 小時(shí)方式選擇位。 當(dāng)它為高電平時(shí), 選擇 12 小時(shí)方式, 在 12 小時(shí)方式下, 位 5 是 AM/PM 位, 此位為邏輯高電平表示 PM。在 24 小時(shí)方式下, 位 5 是第 2 個(gè) 10 小時(shí)位(20-23時(shí))。
上面寄存器地址,轉(zhuǎn)換成16
進(jìn)制的地址如下:
控制寄存器(寫保護(hù)): (寫)0x8E
年寄存器地址: (寫)0x8c (讀)0x8c|0x01
月寄存器地址: (寫)0x88 (讀)0x88|0x01
日寄存器地址: (寫)0x86 (讀)0x86|0x01
時(shí)寄存器地址: (寫)0x84 (讀)0x84|0x01
分寄存器地址: (寫)0x82 (讀)0x82|0x01
秒寄存器地址: (寫)0x80 (讀)0x80|0x01
星期寄存器地址:(寫)0x8a (讀)0x8a|0x01
時(shí)序圖
(1). 讀數(shù)據(jù)時(shí)序
上面的時(shí)序圖是從DS1302寄存器讀取數(shù)據(jù)的時(shí)序圖,讀取數(shù)據(jù)之前,需要先設(shè)置讀取數(shù)據(jù)的寄存器地址,再接收DS1302返回的數(shù)據(jù)。
從時(shí)序圖里得知,開始傳輸數(shù)據(jù)之前,RST保持低電平,時(shí)鐘線保持低電平,開始傳輸數(shù)據(jù)時(shí),RST保持高電平。數(shù)據(jù)是先從低位開始傳輸,在上升沿改變數(shù)據(jù),在下降沿保持?jǐn)?shù)據(jù)穩(wěn)定,數(shù)據(jù)傳輸完畢之后RST保持低電平。
/*
函數(shù)功能: 從DS1302指定寄存器里讀取一個(gè)字節(jié)數(shù)據(jù)
*/
u8 DS1302_ReadByte(u8 addr)
{
u8 n=0,dat=0;
DS1302_RST=1; //然后將DS1302_RST(CE)置高電平。
/*1. 設(shè)置讀取的地址*/
for(n=0;n<8;n++)
{
DS1302_IO=addr&0x01;//數(shù)據(jù)從低位開始傳送
addr>>=1;
DS1302_SCLK=1;//數(shù)據(jù)在上升沿時(shí),DS1302讀取數(shù)據(jù)
DS1302_SCLK=0;//DS1302下降沿時(shí),放置數(shù)據(jù)
}
/*2. 讀取數(shù)據(jù)*/
for(n=0;n<8;n++)
{
dat>>=1;
if(DS1302_IO)dat|=0x80;
DS1302_SCLK=1;
DS1302_SCLK=0;//DS1302下降沿時(shí),放置數(shù)據(jù)
}
DS1302_RST=0;
//必須的操作,復(fù)位時(shí)間
DS1302_IO=0;
DS1302_IO=1;
return dat;
}
(2). 寫數(shù)據(jù)時(shí)序
上面的時(shí)序圖是向DS1302寄存器寫入數(shù)據(jù)的時(shí)序圖,寫入數(shù)據(jù)之前,需要先設(shè)置寫入數(shù)據(jù)的寄存器地址,再寫入實(shí)際的數(shù)據(jù)。
從時(shí)序圖里得知,開始傳輸數(shù)據(jù)之前,RST保持低電平,時(shí)鐘線保持低電平,開始傳輸數(shù)據(jù)時(shí),RST保持高電平。數(shù)據(jù)是先從低位開始傳輸,在上升沿改變數(shù)據(jù),在下降沿保持?jǐn)?shù)據(jù)穩(wěn)定,數(shù)據(jù)傳輸完畢之后RST保持低電平。
/*
函數(shù)功能: 向DS1302指定寄存器里寫一個(gè)字節(jié)數(shù)據(jù)
*/
void DS1302_WriteByte(u8 addr,u8 dat)
{
u8 n;
DS1302_RST=1; //然后將DS1302_RST(CE)置高電平。
/*1. 設(shè)置寫入的地址*/
for(n=0;n<8;n++)
{
DS1302_IO=addr&0x01;//數(shù)據(jù)從低位開始傳送
addr>>=1;
DS1302_SCLK=1;//數(shù)據(jù)在上升沿時(shí),DS1302讀取數(shù)據(jù)
DS1302_SCLK=0;
}
/*2. 寫入數(shù)據(jù)*/
for(n=0;n<8;n++)
{
DS1302_IO=dat&0x01;
dat>>=1;
DS1302_SCLK=1;//數(shù)據(jù)在上升沿時(shí),DS1302讀取數(shù)據(jù)
DS1302_SCLK=0;
}
DS1302_RST=0;//傳送數(shù)據(jù)結(jié)束
}
以下是DS1302的主要特性和工作原理的詳細(xì)介紹:
主要特性
- 時(shí)間與日期功能:DS1302能夠提供精確的時(shí)鐘/日歷功能,包括年、月、日、周、時(shí)、分、秒的計(jì)時(shí),并具有閏年補(bǔ)償功能,有效至2100年。
- 低功耗設(shè)計(jì):適合電池供電的系統(tǒng),工作電壓范圍寬泛,為2.5V至5.5V,且在待機(jī)模式下功耗極低。
- 三線串行接口:通過簡單的三線接口(SCLK、I/O、RST)與微控制器通信,支持同步串行數(shù)據(jù)傳輸,可進(jìn)行讀取和寫入操作。
- 內(nèi)置RAM:包含31字節(jié)的靜態(tài)隨機(jī)存取存儲(chǔ)器(SRAM),可用于存儲(chǔ)與時(shí)間無關(guān)的用戶數(shù)據(jù)。
- 涓流充電能力:具有為備用電源(如電池)提供涓流充電的能力,并且涓流充電功能可以根據(jù)需求開啟或關(guān)閉。
- 自動(dòng)調(diào)整功能:能夠自動(dòng)處理不同月份的天數(shù)差異,包括閏年的2月29日調(diào)整。
- 時(shí)鐘模式選擇:支持12小時(shí)和24小時(shí)兩種時(shí)間顯示模式,具備AM/PM指示。
- 工作溫度范圍:一般適用于-40°C至+85°C的工作溫度范圍,適合多種環(huán)境應(yīng)用。
工作原理
- 初始化與通信:在與DS1302進(jìn)行通信前,需要通過復(fù)位引腳(RST)發(fā)送一個(gè)高電平脈沖以初始化時(shí)鐘芯片,之后通過串行時(shí)鐘線(SCLK)和雙向數(shù)據(jù)線(I/O)進(jìn)行數(shù)據(jù)的讀寫操作。數(shù)據(jù)傳輸采用先寫地址后讀寫數(shù)據(jù)的方式。
- 讀取時(shí)間數(shù)據(jù):微控制器通過發(fā)送適當(dāng)?shù)拿钚蛄校梢宰x取DS1302內(nèi)部的時(shí)鐘數(shù)據(jù)和RAM數(shù)據(jù)。時(shí)間數(shù)據(jù)以BCD碼(二進(jìn)制編碼的十進(jìn)制數(shù))形式存儲(chǔ)。
- 設(shè)置時(shí)間與日期:同樣,通過特定的命令序列,可以向DS1302寫入新的時(shí)間或日期數(shù)據(jù),以調(diào)整時(shí)鐘。
- 電源管理:DS1302設(shè)計(jì)有主電源(Vcc)和備用電源(Vbat)引腳,當(dāng)主電源掉電時(shí),芯片會(huì)自動(dòng)切換到備用電源,保證時(shí)鐘繼續(xù)運(yùn)行。
BCD碼轉(zhuǎn)十進(jìn)制
BCD碼是用4位二進(jìn)制數(shù)來表示1位十進(jìn)制數(shù)中的0~9這10個(gè)數(shù)碼,是一種二進(jìn)制的數(shù)字編碼形式,用二進(jìn)制編碼的十進(jìn)制代碼。BCD碼這種編碼形式利用了四個(gè)位元來儲(chǔ)存一個(gè)十進(jìn)制的數(shù)碼,使二進(jìn)制和十進(jìn)制之間的轉(zhuǎn)換變得方便。
示例代碼:
/*函數(shù)功能: 將十進(jìn)制數(shù)據(jù)轉(zhuǎn)為BCD碼*/
u8 DEC_TO_BCD(u8 val)
{
return ((val/10)<<4)+val%10;
}
/*函數(shù)功能: 將BCD碼數(shù)據(jù)轉(zhuǎn)為十進(jìn)制格式*/
u8 BCD_TO_DEC(u8 val)
{
return (val&0x0f)+(val>>4)*10;
}
DS1302示例代碼
下面代碼里實(shí)現(xiàn)DS1302的寄存器讀寫,時(shí)間的設(shè)置與讀取,在主函數(shù)里判斷了之前DS1302是否正常工作,如果DS1302處于停止計(jì)時(shí)狀態(tài),就重新設(shè)置時(shí)間,在循環(huán)代碼里,每1秒鐘,向串口打印讀取的時(shí)間。
**(硬件平臺(tái)說明:CPU 是STC90C516RD **、晶振頻率12MHZ、工作在12T模式下、一個(gè)機(jī)器周期為1us時(shí)間)
示例代碼:
#include <reg51.h>
//定義ds1302使用的IO口
sbit DS1302_IO=P3^4;
sbit DS1302_RST=P3^5;
sbit DS1302_SCLK=P3^6;
u8 DS1302_TIME[7]; //存放讀取的時(shí)間
/*
函數(shù)功能: 將十進(jìn)制數(shù)據(jù)轉(zhuǎn)為BCD碼
*/
u8 DEC_TO_BCD(u8 val)
{
return ((val/10)<<4)+val%10;
}
/*
函數(shù)功能: 將BCD碼數(shù)據(jù)轉(zhuǎn)為十進(jìn)制格式
*/
u8 BCD_TO_DEC(u8 val)
{
return (val&0x0f)+(val>>4)*10;
}
void DS1302_Init(void)
{
DS1302_RST=0;
DS1302_SCLK=0;//先將DS1302_SCLK置低電平。
}
/*
函數(shù)功能: 向DS1302指定寄存器里寫一個(gè)字節(jié)數(shù)據(jù)
*/
void DS1302_WriteByte(u8 addr,u8 dat)
{
u8 n;
DS1302_RST=1; //然后將DS1302_RST(CE)置高電平。
/*1. 設(shè)置寫入的地址*/
for(n=0;n<8;n++)
{
DS1302_IO=addr&0x01;//數(shù)據(jù)從低位開始傳送
addr>>=1;
DS1302_SCLK=1;//數(shù)據(jù)在上升沿時(shí),DS1302讀取數(shù)據(jù)
DS1302_SCLK=0;
}
/*2. 寫入數(shù)據(jù)*/
for(n=0;n<8;n++)
{
DS1302_IO=dat&0x01;
dat>>=1;
DS1302_SCLK=1;//數(shù)據(jù)在上升沿時(shí),DS1302讀取數(shù)據(jù)
DS1302_SCLK=0;
}
DS1302_RST=0;//傳送數(shù)據(jù)結(jié)束
}
/*
函數(shù)功能: 從DS1302指定寄存器里讀取一個(gè)字節(jié)數(shù)據(jù)
*/
u8 DS1302_ReadByte(u8 addr)
{
u8 n=0,dat=0;
DS1302_RST=1; //然后將DS1302_RST(CE)置高電平。
/*1. 設(shè)置讀取的地址*/
for(n=0;n<8;n++)
{
DS1302_IO=addr&0x01;//數(shù)據(jù)從低位開始傳送
addr>>=1;
DS1302_SCLK=1;//數(shù)據(jù)在上升沿時(shí),DS1302讀取數(shù)據(jù)
DS1302_SCLK=0;//DS1302下降沿時(shí),放置數(shù)據(jù)
}
/*2. 讀取數(shù)據(jù)*/
for(n=0;n<8;n++)
{
dat>>=1;
if(DS1302_IO)dat|=0x80;
DS1302_SCLK=1;
DS1302_SCLK=0;//DS1302下降沿時(shí),放置數(shù)據(jù)
}
DS1302_RST=0;
//必須的操作,復(fù)位時(shí)間
DS1302_IO=0;
DS1302_IO=1;
return dat;
}
/*
函數(shù)功能: 設(shè)置DS1302芯片的時(shí)間
DS1302的時(shí)間基準(zhǔn)是從2000年開始的,設(shè)置年份時(shí)要減去2000再傳入設(shè)置
例如:DS1302_WriteTime(20,1,18,14,46,20,6);
*/
void DS1302_WriteTime(u8 year,u8 mon,u8 mday,u8 hour,u8 min,u8 sec,u8 week)
{
DS1302_WriteByte(0x8E,0x00); //禁止寫保護(hù),就是關(guān)閉寫保護(hù)功能
DS1302_WriteByte(0x8c,DEC_TO_BCD(year)); //設(shè)置年
DS1302_WriteByte(0x88,DEC_TO_BCD(mon)); //設(shè)置月
DS1302_WriteByte(0x86,DEC_TO_BCD(mday)); //設(shè)置日
DS1302_WriteByte(0x84,DEC_TO_BCD(hour)); //設(shè)置時(shí)
DS1302_WriteByte(0x82,DEC_TO_BCD(min)); //設(shè)置分
DS1302_WriteByte(0x80,DEC_TO_BCD(sec)); //設(shè)置秒
DS1302_WriteByte(0x8a,DEC_TO_BCD(week)); //設(shè)置星期
DS1302_WriteByte(0x8E,0x80); //打開寫保護(hù)功能
}
/*
函數(shù)功能: 讀取DS1302時(shí)鐘的時(shí)間
DS1302寄存器的最低位是讀寫位,0是寫,1是讀
*/
void DS1302_ReadTime(void)
{
DS1302_TIME[0]=BCD_TO_DEC(DS1302_ReadByte(0x8c|0x01));//讀取年
DS1302_TIME[1]=BCD_TO_DEC(DS1302_ReadByte(0x88|0x01));//讀取月
DS1302_TIME[2]=BCD_TO_DEC(DS1302_ReadByte(0x86|0x01));//讀取日
DS1302_TIME[3]=BCD_TO_DEC(DS1302_ReadByte(0x84|0x01));//讀取時(shí)
DS1302_TIME[4]=BCD_TO_DEC(DS1302_ReadByte(0x82|0x01));//讀取分
DS1302_TIME[5]=BCD_TO_DEC(DS1302_ReadByte(0x80|0x01));//讀取秒
DS1302_TIME[6]=BCD_TO_DEC(DS1302_ReadByte(0x8a|0x01));//讀取星期
}
int main()
{
u8 stat;
UART_Init(); //初始化串口波特率為4800
DS1302_Init();
stat=DS1302_ReadByte(0x80|0x01);//讀取秒
if(stat&0x80)
{
DS1302_WriteTime(2020-2000,1,18,16,33,33,6);
}
else
{
printf("DS1302 OKrn");
}
while(1)
{
DS1302_ReadTime();
printf("DS1302:%d-%d-%d %d:%d:%d %drn",
(int)DS1302_TIME[0]+2000,
(int)DS1302_TIME[1],
(int)DS1302_TIME[2],
(int)DS1302_TIME[3],
(int)DS1302_TIME[4],
(int)DS1302_TIME[5],
(int)DS1302_TIME[6]
);
DelayMs(1000);
}
}