DS1302的引腳排列,其中Vcc2為主電源,VCC1為後備電源。在主電源關閉的情況下,也能保持時鐘的連續運行。DS1302由Vcc1或Vcc2兩者中的較大者供電。當Vcc2大於Vcc1+0.2V時,Vcc2給DS1302供電。當Vcc2小於Vcc1時,DS1302由Vcc1供電。
X1和X2是振蕩源,外接32.768kHz晶振。RST是復位/片選線,通過把RST輸入驅動置高電平來啟動所有的數據傳送。RST輸入有兩種功能:首先,RST接通控制邏輯,允許地址/命令序列送入移位寄存器;其次,RST提供終止單字節或多字節數據傳送的方法。
當RST為高電平時,所有的數據傳送被初始化,允許對DS1302進行操作。如果在傳送過程中RST置為低電平,則會終止此次數據傳送,I/O引腳變為高阻態。上電運行時,在Vcc》2.0V之前,RST必須保持低電平。只有在SCLK為低電平時,才能將RST置為高電平。
DS1302的電路一個重點就是時鐘電路,它所使用的晶振是一個32.768k的晶振,晶振外部也不需要額外添加其他的電容或者電阻電路了。時鐘的精度,首先取決於晶振的精度以及晶振的引腳負載電容。如果晶振不準或者負載電容過大過小,都會導致時鐘誤差過大。在這一切都搞定後,最終一個考慮因素是晶振的溫漂。隨著溫度的變化,晶振往往精度會發生變化,因此,在實際的系統中,其中一種方法就是經常校對。比如我們所用的電腦的時鐘,通常我們會設置一個選項「將計算機設置於internet時間同步」。選中這個選項後,一般可以過一段時間,我們的計算機就會和internet時間校準同步一次。
應用電路二:
1腳VCC2是主電源正極的引腳,2腳X1和3腳X2是晶振輸入和輸出引腳,4腳GND是負極,5腳CE是使能引腳,接單片機的IO口,6腳I/O是數據傳輸引腳,接單片機的IO口,7腳SCLK是通信時鐘引腳,接單片機的IO口,8腳VCC1是備用電源引腳。考慮到KST-51開發板是一套以學習為目的的板子,加上備用電池對航空運輸和攜帶不方便,所以8腳沒有接備用電池,而是接了一個10uF的電容,這個電容就相當於一個電量很小的電池,經過試驗測量得出其可以在系統掉電後仍維持DS1302運行1分鐘左右,如果大家想運行時間再長,可以加大電容的容量或者換成備用電池,如果掉電後不需要它再維持運行,也可以乾脆懸空,如圖15-7和圖15-8所示。
涓流充電功能,基本也用不到,因為實際應用中很少會選擇可充電電池作為備用電源,成本太高,本課程也不講了,大家作為選學即可。我們使用的時候直接用5V電源接一個二極體,在主電源上電的情況下給電容充電,在主電源掉電的情況下,二極體可以防止電容向主電路放電,而僅用來維持DS1302的供電,這種電路的最大用處是在電池供電系統中更換主電池的時候保持實時時鐘的運行不中斷,1分鐘的時間對於更換電池足夠了。此外,通過我們的使用經驗,在DS1302的主電源引腳串聯一個1K電阻可以有效的防止電源對DS1302的衝擊,R6就是這個電阻,而R9、R26、R32都是上拉電阻。
DS1302寫入時序通過命令的方式寫入年月日時分秒信息。 命令格式為2位元組。 第一字節為地址,第二字節為內容。
寫入邏輯:
1 將RST先拉低
2 將SCLK拉低(如果不拉低,且本來是高電平,則瞬間就發出了一個bit,我們還沒放數據呢)
3 再RST拉高。。 形成一個上升沿
4 在IO口放入一個bit(字節發送順序,從低位到高位)
5 設SCLK為高電平,形成上升沿,這時候DS1302就會讀取IO口的數據存入它的寄存器。
6 拉低SCLK,為下一個字節做準備。,跳轉到5 ,直到發送完所有的16個字節
7 拉低RST,整個寫入過程完成。
DS1302命令格式雖然命令字節看起來很複雜,但編寫程序很簡單,比如你要設置秒為13秒。那麼發送的兩個字節的數據應該是什麼?第一個字節是0x80(寫入秒的命令,見上圖)。第二個數據,第四位為3,高四位為1。就是(1<<4)|3,為0x13
其他的年月日類似。比較特殊的幾個位說一下。
(1)如果想讓錶停下來
發送一個設置秒的命令,第二個字節最高位置為1,即,發送0x800x80即可。
(2)小時的第二個字節的最高位控制著12還是24進位
Arduino控制DS1302連線 Arduino控制DS1302程序/* * 讀寫DS1302 時鐘晶片
* @author Yangtf
* 很棒的文檔 http://www.21ic.com/jichuzhishi/datasheet/DS1302/data/185858.html
* 時序圖 http://www.21ic.com/d/file/201307/0a93263a0126e1580cc71c89dce1fda9.jpg
*
*/
#define RST 7
#define SCLK 6
#define IO 5
//#define L(item) digitalWrite((item),LOW)
//#define H(item) digitalWrite((item),HIGH)
#define uchar unsigned char
void setup() {
pinMode(RST,OUTPUT);
pinMode(SCLK,OUTPUT);
pinMode(IO,OUTPUT);
Serial.begin(9600);
attachInterrupt(0, settm, FALLING );
}
void writeData(unsigned char addr,unsigned char dat)
{
pinMode(IO,OUTPUT);
digitalWrite(RST,LOW); //下拉低,再拉高
digitalWrite(SCLK,LOW) ; //SCLK的上升沿, 晶片會讀取IO埠 d
elayMicroseconds(1);
digitalWrite(RST,HIGH);
int i;
for(i =0;i《8;i++)
{
digitalWrite(SCLK,LOW);
digitalWrite(IO, addr&1);
addr =addr》》1;
digitalWrite(SCLK,HIGH);
delayMicroseconds(1);
}
for(i =0;i《8;i++){
digitalWrite(SCLK,LOW);
digitalWrite(IO, dat&1);
dat =dat》》1;
digitalWrite(SCLK,HIGH);
delayMicroseconds(1);
}
digitalWrite(RST,LOW);
}
uchar readData(uchar addr){
addr = addr | 1; //讀操作最低位置為1
pinMode(IO,OUTPUT);
digitalWrite(RST,LOW); //下拉低,再拉高
digitalWrite(SCLK,LOW) ; //SCLK的上升沿, 晶片會讀取IO埠
delayMicroseconds(1);
digitalWrite(RST,HIGH);
int i;
for(i =0;i《8;i++){
digitalWrite(SCLK,LOW);
digitalWrite(IO, addr&1);
addr =addr》》1;
digitalWrite(SCLK,HIGH);
delayMicroseconds(1);
}
pinMode(IO,INPUT);
int dat = 0;
for(i =0;i《8;i++){
digitalWrite(SCLK,LOW);
delayMicroseconds(10);
uchar b = digitalRead(IO);
dat = dat 》》1; //先向右平移
dat = dat | (b《《7); //將所得放入最高位
digitalWrite(SCLK,HIGH);
delayMicroseconds(1);
}
digitalWrite(RST,LOW);
return dat ;
}
#define SECOND 0x80
#define MIN 0x82
#define HOUR 0x84
#define DAY 0x86
#define MONTH 0x88
#define YEAR 0x8C
#define WEEK 0x8A
void writeTimeUnit(
uchar TYPE,uchar data){
uchar high = data / 10;
uchar low = data % 10;
uchar d = ((data /10) 《《 4) | (data % 10);
writeData(TYPE,data);
}
uchar readTimeUnit(uchar TYPE){
uchar r = readData(TYPE);
r = 10*(r 》》 4)+ (r & 0xf);
return r;
}
void writeAllTm(uchar tm[]){
uchar s = SECOND;
for(uchar i=0;i《5;i++){
writeTimeUnit(s,tm[5-i]);
s+=2; } writeTimeUnit(YEAR,tm[0]);
} void readAllTm(uchar tm[]){
uchar s = SECOND;
for(uchar i=0;i《5;i++){
tm[5-i] = readTimeUnit(s);
s+=2;
}
tm[0] = readTimeUnit(YEAR);
tm[6] = readTimeUnit(WEEK);
}
void printTm(uchar tm[]){
Serial.print(tm[0]);
Serial.print(「-」);
Serial.print(tm[1]);
Serial.print(「-」);
Serial.print(tm[2]);
Serial.print(「 」);
Serial.print(tm[3]);
Serial.print(「:」);
Serial.print(tm[4]);
Serial.print(「:」);
Serial.print(tm[5]);
Serial.print(「 week 」);
Serial.print(tm[6]);
Serial.println();
}
uchar st = 0;
void loop() {
uchar tm[7] = {0};
readAllTm(tm);
printTm(tm);
delay(1000);
}
void settm()//中斷函數
{
uchar tm[] = {11,12,13,4,5,6 ,0}; // 2011-12-22 3:4:1
Serial.println(「set tm 。。.」);
writeAllTm(tm);
}