實(shí)時(shí)時(shí)鐘DS1307 介紹:
DS1307是低功耗、兩線制串行讀寫接口、日歷和時(shí)鐘數(shù)據(jù)按BCD碼存取的時(shí)鐘/日歷芯片。它提供秒、分、小時(shí)、星期、日期、月和年等時(shí)鐘日歷數(shù)據(jù)。另外它還集成了如下幾點(diǎn)功能:
(1)56 字節(jié)掉電時(shí)電池保持的NV SRAM 數(shù)據(jù)存儲(chǔ)器
(3)掉電檢測(cè)和自動(dòng)切換電池供電模式
DS1307 把8 個(gè)寄存器和56 字節(jié)的RAM 進(jìn)行了統(tǒng)一編址,具體地址和寄器數(shù)據(jù)組織格式如下表:

(日期為BCD碼)

在讀寫過程中DS1307 內(nèi)部維護(hù)一個(gè)地址指針,通過寫操作可對(duì)它 值,讀和寫每一字節(jié)時(shí)自動(dòng)加一,當(dāng)指針越過DS1307 內(nèi)部RAM 尾 時(shí)指針將返回到0 地址處。
DS1307 的時(shí)鐘和日歷數(shù)據(jù)按BCD 碼存儲(chǔ)。
ds1307引腳圖及功能
DS1307
串行實(shí)時(shí)時(shí)鐘記錄年、月、日、時(shí)、分、秒、星期及日期; AM、PM 分別表示上午和下午; 56 個(gè)字節(jié)的NVRAM存放數(shù)據(jù); 2線串口; 可編程的方波輸出;電源故障檢測(cè)及自動(dòng)切換電路;電池電流小于500nA。
主要引腳定義如下: X1、32.768kHz 晶振接入端;
VBAT:X2:+3V 電池電壓輸入;
SDA: 串行數(shù)據(jù);
SCL:串行時(shí)鐘;
SQW/OUT:方波/輸出驅(qū)動(dòng)器。

方波信號(hào)輸出功能
方波信號(hào)輸出功能從SQW/OUT 引腳輸出設(shè)置頻率的方波,CONTROL 寄存器用于控制SQW/OUT 腳的輸出。
BIT7(OUT):此位表示在方波輸出被禁止時(shí)(BIT4=0),SQW/OUT 引腳的邏輯電平,在BIT4=0(SQWE=0方波輸出禁止)時(shí),若BIT7(OUT) 為1 則SQL/OUT 引腳為高電平, 反之亦然。
BIT4(SQWE)方波輸出允許/禁止控制位,SQWE =1 允許方波輸出(有效);BIT4=0 禁止方波輸出。
BIT0(RS0)、BIT1(RS1)于設(shè)定輸出波形的頻率,如下表:

要注意的是,00h 地址的第7 位為器件時(shí)鐘允許位(CH),由于在在開始上電時(shí)內(nèi)部RAM內(nèi)容隨機(jī),所以在初始化時(shí)將CH 位設(shè)零(時(shí)鐘允許)是非常重要的。
DS1307 在TWI 總線上是從器件,地址(SLA)固定為”11010000”
DS1307 寫操作 TWI 被控接收模式
主控器件按如下順序?qū)?shù)據(jù)寫入到DS1307 寄存器或內(nèi)部RAM 中:
第一步.START 信號(hào)
第二步。寫SLA+W(0xd0)字節(jié),DS1307 應(yīng)答(ACK)
第三步。寫1 字節(jié)內(nèi)存地址(在以下第四步寫入的第一字節(jié)將存入到DS1307 內(nèi)該地址處),DS1307應(yīng)答。
第四步。寫數(shù)據(jù)(可寫多個(gè)字節(jié),每一字節(jié)寫入后DS1307 內(nèi)部地址計(jì)數(shù)器加一,DS1307 應(yīng)答)
第五步.STOP 信號(hào)
DS1307 讀操作TWI 被控發(fā)送模式
主控器件按如下順序?qū)S1307 寄存器或內(nèi)部RAM 數(shù)據(jù)讀?。?/p>
第一步.START 信號(hào)
第二步。寫SLA+R(0xd1)字節(jié),DS1307 應(yīng)答(ACK)
第三步。讀數(shù)據(jù)(可讀多個(gè)字節(jié),讀取數(shù)據(jù)的DS1307 內(nèi)部地址由上次寫操作或讀操作決定,讀取每一字節(jié)DS1307 內(nèi)部地址計(jì)數(shù)器加一,主器件應(yīng)答,讀取最后一字節(jié)時(shí)主器件回應(yīng)一NACK信號(hào))
第四步.STOP 信號(hào)
典型應(yīng)用電路圖

特征
實(shí)時(shí)時(shí)鐘(RTC)計(jì)算秒,分鐘,小時(shí),月,月,日的日期周和年份,閏年補(bǔ)償,有效期至2100年
56字節(jié),由電池供電,通用RAM與無(wú)限寫操作I2C串行接口可編程方波輸出信號(hào)
自動(dòng)電源失效檢測(cè)和切換電路消耗的電池備份超過500nA的少與振蕩器運(yùn)行模式
可選的工業(yè)溫度范圍:-40°C至+ 85°C提供8引腳塑料DIP或SO
美國(guó)保險(xiǎn)商實(shí)驗(yàn)室(UL)認(rèn)證
DS1307 C語(yǔ)言程序
//********************************************************************
//***************************DS1307調(diào)試 *****************************
//********************************************************************
//**DS1307實(shí)時(shí)時(shí)鐘芯片地址0xD0 讀0xD1 寫0xD0 *********************
//********************************************************************
#include《reg51.h》 //單片機(jī)80C51
sbit SCL=P1^1; //串口時(shí)鐘信號(hào)
sbit SDA=P1^0; //串口數(shù)據(jù)信號(hào)
sbit clock=P1^2; //調(diào)試用脈沖輸出信號(hào)**************
unsigned char error; //通訊正常error=0x10;超時(shí)error=0x11
void delay(int i); //延時(shí)子函數(shù)
void TimeInitial(); //時(shí)鐘初始化子函數(shù)
void Start_I2C(); //打開串口子函數(shù)
void Stop_I2C (); //關(guān)閉串口子函數(shù)
void Ack_I2C(); //接受應(yīng)答信號(hào)并判斷是否正常子函數(shù)
void SendAck(); //發(fā)送應(yīng)答信號(hào)子函數(shù)
void SendNotAck(); //發(fā)送非應(yīng)答信號(hào)子函數(shù)
void Send_I2C (int ch); //向總線上發(fā)送一個(gè)字節(jié)
unsigned int Receive_I2C(); //在總線上接受一個(gè)字節(jié)
int read_time(int address); //從芯片D1307讀出10為字節(jié) 地址1:秒 2:分 3:時(shí) 4:星期 5:號(hào) 6:月7:年 8 控制字
void write_time(int address,int date); //向芯片D1307 之中地址為address的寄存器寫入數(shù)據(jù)date 僅為八位字節(jié)
void main() //主程序************************************************************
{
TimeInitial(); //時(shí)鐘初始化
write_time(0x07,0x10); //向芯片D1307寫入控制字(芯片地址0X07)0x10 控制字:1晶振使能(0有效)4:SOUT方波輸出 7、8:方波頻率編碼
while(1)
{
}
}
void TimeInitial() //時(shí)鐘初始化
{
TMOD=0x10; //時(shí)鐘選擇方式2 T1時(shí)鐘
TH1=0x15;
TL1=0xA0; //定時(shí)60ms
EA=1; //中斷準(zhǔn)許
ET1=1; //時(shí)鐘T1 溢出中斷準(zhǔn)許
TR1=1; //啟動(dòng)時(shí)鐘T1
}
//**********************************延時(shí)
void delay(int i)
{
int j,h;
for(j=1;j《99;j++)
{
for(h=0;h《i;h++)
;
}
}
//**********************************傳送啟動(dòng)
void Start_I2C()
{
EA=0; //關(guān)閉中斷
SCL=0; //總線放空,以便更改總線數(shù)據(jù)
delay(1); //延時(shí)
SDA=1; //發(fā)送I2C總線起始條件的數(shù)據(jù)信號(hào)1以便總線使能時(shí)產(chǎn)生下降沿
delay(1); //延時(shí)
SCL=1; //發(fā)送I2C總線起始條件的時(shí)鐘信號(hào)
delay(1); //延時(shí)
SDA=0; //產(chǎn)生下降沿 總線傳輸開始
delay(1); //延時(shí)
SCL=0; //時(shí)鐘線從高到低一次跳變,總線放空 準(zhǔn)備傳輸數(shù)據(jù)
}
//**********************************傳送關(guān)閉
void Stop_I2C ()
{
SCL=0; //發(fā)送I2C總線時(shí)鐘信號(hào)放空
SDA=0; //發(fā)送I2C總線停止條件的數(shù)據(jù)信號(hào)0以便產(chǎn)生上升沿
delay(1); //延時(shí)
SCL=1; //時(shí)鐘線從低到高一次跳變 總線 使能
delay(1); //延時(shí)
SDA=1; //發(fā)送I2C總線數(shù)據(jù)信號(hào)產(chǎn)生上升沿 終止傳送
delay(1); //延時(shí)
SCL=0; //發(fā)送I2C總線時(shí)鐘信號(hào)放空
delay(1);
SDA=0; //發(fā)送I2C總線放空 準(zhǔn)備下次動(dòng)作
EA=1; //傳輸結(jié)束開啟中斷
}
//**********************************傳送響應(yīng)
void Ack_I2C()
{
unsigned char errtime=255; //因故障接收方無(wú)ACK,超時(shí)值為255。
SDA=1; //數(shù)據(jù)線升高,以便捕捉相應(yīng)信號(hào),(相應(yīng)信號(hào):拉低數(shù)據(jù)線)
SCL=1; // 主機(jī)放出一脈沖,等待捕捉相應(yīng)信號(hào)
error=0x10; //通訊正常(即:接受到了相應(yīng)信號(hào))為0X10;
while(SDA) //等待捕捉相應(yīng)信號(hào),信號(hào)沒有到來前一直保持循環(huán),信號(hào)到來后迅速跳出循環(huán)
{
errtime--; //每循環(huán)一次,倒計(jì)時(shí)減一
if(!errtime) //判斷倒計(jì)時(shí)是否減到了0,即循環(huán)了255次,如果減到了0,判定此次通訊未接受到響應(yīng)信號(hào),傳送失敗
{
Stop_I2C (); //傳送失敗,停止傳送
error=0x11; //傳送結(jié)果未傳送失敗0x11
return; //跳出循環(huán)
}
}
SCL=0; //無(wú)論傳送是否正確,都需放空總線,以備后用
}
//**********************************向總線傳送響應(yīng)
void SendAck()
{
SDA=0; //數(shù)據(jù)線保持拉低,時(shí)鐘線發(fā)生一次從高低的跳變 發(fā)送一個(gè)應(yīng)答信號(hào)
delay(1);
SCL=1;
delay(1);
SCL=0;
}
//**********************************向總線傳送非響應(yīng)
void SendNotAck()
{
SDA=1; //數(shù)據(jù)線保持高,時(shí)鐘線發(fā)生一次從高低的跳變 沒有應(yīng)答
delay(1);
SCL=1;
delay(1);
SCL=0;
}
//**********************************向總線傳送字節(jié)
void Send_I2C (int ch)
{
int i;
for (i=1;i《=8;i++) //發(fā)送八位
{
SCL=0; //總線放空
delay(1); //延時(shí)
SDA=(ch&0x80); //根據(jù)給定數(shù)據(jù),又高位到低位逐步提出字節(jié)位,發(fā)送到總線上
ch《《=1; //左循環(huán)以便輸出下一位
delay(1); //延時(shí)
SCL=1; //總線使能,發(fā)送總線數(shù)據(jù)
delay(1); //延時(shí)
}
SCL=0; //總線8位傳送完成,總線放空
}
//**********************************向總線讀入字節(jié)
unsigned int Receive_I2C()
{
unsigned char i,a;
SDA=1; //不知道為啥,1的時(shí)候讀入正確 0的時(shí)候讀入全部為0;
for (i=1;i《=8;i++) //讀入八個(gè)位
{
a《《=1; // 讀入數(shù)據(jù)左循環(huán)
SCL=0; //總線放空
delay(1);
SCL=1; //時(shí)鐘做一次從低到高的跳變 可以接收一位數(shù)據(jù)
delay(1);
a|=SDA; // 將數(shù)據(jù)編入變量a
}
SCL=0; //總線放空
return a; //反饋接收到的信息
}
//**********************************向芯片D1307 之中地址為address的寄存器寫入數(shù)據(jù)date 僅為八位字節(jié)
void write_time(int address,int date)
{
Start_I2C(); //啟動(dòng)總線
Send_I2C (0xD0); //呼叫芯片D1307,并定義為 寫 動(dòng)作
Ack_I2C(); //等待響應(yīng)信號(hào)
Send_I2C (address); //發(fā)送地址
Ack_I2C(); //等待響應(yīng)信號(hào)
Send_I2C (date); //發(fā)送數(shù)據(jù)
Ack_I2C(); //等待響應(yīng)信號(hào)
Stop_I2C (); //停止總線
}
//****************從芯片D1307讀出10為字節(jié) 地址1:秒 2:分 3:時(shí) 4:星期 5:號(hào) 6:月7:年 8 控制字
int read_time(int address)
{
int a[10]; //定義一個(gè)數(shù)組以便接受數(shù)據(jù)
int i=1;
Start_I2C(); //啟動(dòng)傳送
Send_I2C (0xD0); //呼叫芯片D1307,并定義為 寫 動(dòng)作
Ack_I2C(); //等待響應(yīng)信號(hào)
Send_I2C (0x00); //發(fā)送起始地址
Ack_I2C(); //等待響應(yīng)信號(hào)
Stop_I2C (); //關(guān)閉總線
Start_I2C(); //啟動(dòng)總線
Send_I2C (0xD1); //呼叫芯片D1307,并定義為 讀 動(dòng)作
SendAck(); //發(fā)送應(yīng)答就位,準(zhǔn)備接受數(shù)據(jù)
for(i;i《10;i++)
{
a[i]=Receive_I2C(); //接受自初始地址開始的10個(gè)字節(jié) 地址1:秒 2:分 3:時(shí) 4:星期 5:號(hào) 6:月7:年 8 控制字
SendAck(); //每成功接受一位發(fā)送一個(gè)響應(yīng)信號(hào) 以便接受下一位
}
Stop_I2C (); //接受完成停止
return a[address]; //反饋所需數(shù)據(jù)
}
void t1(void) interrupt 3 using 0 //T1溢出中斷
{
TH1=0x15;
TL1=0xa0; //重新載入60ms
clock=~clock; //調(diào)試用脈沖
P0=read_time(1); //將實(shí)時(shí)時(shí)鐘 秒 送入P0口
}
