|
百度ds1302 寫道
DS1302 是美國DALLAS公司推出的一種高性能、低功耗、帶RAM的實時時鐘電路,它可以對年、月、日、周日、時、分、秒進行計時,具有閏年補償功能,工作電壓為2.5V~5.5V。采用三線接口與CPU進行同步通信,并可采用突發(fā)方式一次傳送多個字節(jié)的時鐘信號或RAM數(shù)據(jù)。DS1302內部有一個31×8的用于臨時性存放數(shù)據(jù)的RAM寄存器。DS1302是DS1202的升級產(chǎn)品,與DS1202兼容,但增加了主電源/后備電源雙電源引腳,同時提供了對后備電源進行涓細電流充電的能力。
DS1302的引腳排列,其中Vcc1為后備電源,VCC2為主電源。在主電源關閉的情況下,也能保持時鐘的連續(xù)運行。DS1302由Vcc1或Vcc2兩者中的較大者供電。當Vcc2大于Vcc1+0.2V時,Vcc2給DS1302供電。當Vcc2小于Vcc1時,DS1302由Vcc1供電。X1和X2是振蕩源,外接32.768kHz晶振。RST是復位/片選線,通過把RST輸入驅動置高電平來啟動所有的數(shù)據(jù)傳送。RST輸入有兩種功能:首先,RST接通控制邏輯,允許地址/命令序列送入移位寄存器;其次,RST提供終止單字節(jié)或多字節(jié)數(shù)據(jù)傳送的方法。當RST為高電平時,所有的數(shù)據(jù)傳送被初始化,允許對DS1302進行操作。如果在傳送過程中RST置為低電平,則會終止此次數(shù)據(jù)傳送,I/O引腳變?yōu)楦咦钁B(tài)。上電運行時,在Vcc>2.0V之前,RST必須保持低電平。只有在SCLK為低電平時,才能將RST置為高電平。I/O為串行數(shù)據(jù)輸入輸出端(雙向),后面有詳細說明。SCLK為時鐘輸入端。 下圖為DS1302的引腳功能圖
.....................................................................................
efab4a01-ab2c-39ab-a165-3f91d93be859.png (30.19 KB, 下載次數(shù): 34)
下載附件
2017-1-14 23:30 上傳
7f37bf47-6742-3446-9cfc-f76d0f4dd150.png (38.77 KB, 下載次數(shù): 26)
下載附件
2017-1-14 23:30 上傳
我在淘寶上花了幾塊錢買了個山寨的1302模塊,湊合著可以用,
但是模塊上的sclk,io,RST這3個腳沒有上拉電阻,自己加上去了,汗!
不加上拉電阻,顯示的時鐘很容易發(fā)生錯誤
好了不多說,貼代碼
本程序只顯示時間,沒有年份和月份...- #include "my51.h"
- #include "smg.h"
- #include "ds1302.h"
- void main() //ds1302顯示時鐘
- {
- ds1302_initSet();//初始化
- //ds1302_stop(); 停掉1302,進入省電模式
- while(1)
- {
- ds1302_readRTC();_nop_(); //讀取時鐘數(shù)據(jù)
- displaySMG(ds1302_processTimeData());//處理數(shù)據(jù)并送數(shù)碼管顯示
- }
- }
復制代碼
- #ifndef _DS1302_H
- #define _DS1302_H
- #include "my51.h"
- sbit rst=P3^4; //片選總線
- sbit sda=P3^5; //數(shù)據(jù)總線
- sbit scl=P3^6; //時鐘線
- extern u8 data smgWela[7]; //數(shù)碼管顯示參數(shù)
- extern u8 data timeData[7]; //年,周,月,日,時,分,秒的初值
- //void ds1302_setUnCharger() //充電控制,禁止充電
- //void ds1302_stop() ; //暫停ds1302,進入超低功耗模式
- u8* ds1302_processTimeData(); //處理時鐘數(shù)據(jù),送給數(shù)碼管顯示
- void ds1302_readRTC(); //讀取所有時鐘數(shù)據(jù)的BCD碼
- void ds1302_initSet() ; //設置初始化數(shù)據(jù)
- u8 ds1302_readData(u8 addr); //從ds1302讀一個字節(jié),讀的時候會先寫地址
- void ds1302_writeByte(u8 dat); //寫一個字節(jié)
- void ds1302_writeData(u8 addr,u8 dat); //向指定地址寄存器寫數(shù)據(jù)
- #endif
復制代碼
- #include "ds1302.h"
- data u8 timeData[7]={10,6,4,17,11,20,55};
- code u8 writeAddr[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};//寫年周月日時分秒寄存器地址指令
- code u8 readAddr[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};//讀的指令地址
- void ds1302_writeData(u8 addr,u8 dat) //向指定地址寄存器寫數(shù)據(jù)
- {
- rst=0; _nop_();
- scl=0; _nop_();
- rst=1; _nop_();
- ds1302_writeByte(addr); //先寫入地址
- ds1302_writeByte(dat);
- rst=0;_nop_(); //關閉
- sda=1; //釋放
- scl=1;
- }
- void ds1302_writeByte(u8 dat) //寫一個字節(jié)
- {
- u8 i=0;
- for(i=0;i<8;i++)
- {
- scl=0; //時鐘線拉低
- sda=dat&0x01; //數(shù)據(jù)從最低位開始賦值
- dat>>=1;
- scl=1;_nop_(); //上升沿寫入一位
- }
- }
- u8 ds1302_readData(u8 addr) //從ds1302讀一個字節(jié),讀的時候會先寫地址
- {
- u8 i,value=0;
- rst=0;_nop_();
- scl=0;_nop_();
- sda=1;_nop_();
- rst=1;_nop_();
- ds1302_writeByte(addr); //先寫入要讀的地址
- _nop_();
- sda=1;_nop_();
- for(i=0;i<8;i++)
- {
- value>>=1;
- scl=0;_nop_(); //下降沿開始后提取有效數(shù)據(jù)
- if(sda) //讀數(shù)據(jù)
- {
- value|=0x80;//高電平手動置位保存數(shù)據(jù),
- } //低電平數(shù)據(jù)value最高位默認已經(jīng)是0
- scl=1; //為下一次讀取數(shù)據(jù)做準備
- }
- rst=0;
- return value;
- }
-
- void ds1302_initSet() //設置初始化數(shù)據(jù)
- {
- u8 i,j;
- for(i=0;i<7;i++)//將初始化數(shù)據(jù)處理成BCD碼
- {
- j = timeData[i] / 10;
- timeData[i]=timeData[i]%10;
- timeData[i]=timeData[i]+j*16;
- }
- ds1302_writeData(0x8e,0x00); //清除寫保護
- for(i=0;i<7;i++)
- { //將時鐘日歷數(shù)據(jù)經(jīng)過轉換后的BCD碼寫到7個時鐘日歷寄存器中
- ds1302_writeData(writeAddr[i],timeData[i]);
- }
- ds1302_writeData(0x90,0x5c); //禁止充電,降低功耗,針對不可充電電池
- //ds1302_writeData(0x90, 0xa6);//開啟充電,用一個二極管,用4k電阻
- ds1302_writeData(0x8e,0x80); //使能寫保護
- }
-
- void ds1302_readRTC() //讀取所有時鐘數(shù)據(jù)的BCD碼
- {
- u8 i;
- for(i=0;i<7;i++)
- { //讀取的時候會把時鐘日歷的7個寄存器中的數(shù)據(jù)全部讀取,并保存到timeData[]
- timeData[i]=ds1302_readData(readAddr[i]);
- }
- }
- u8* ds1302_processTimeData() //顯示時鐘,暫時只顯示時間
- {
- smgWela[5]=timeData[6] & 0x0f;//提取低4位
- smgWela[4]=timeData[6] >> 4;//提取高4位
- smgWela[3]=timeData[5]& 0x0f;
- smgWela[2]=timeData[5]>> 4;
- smgWela[1]=timeData[4]& 0x0f;
- smgWela[0]=timeData[4]>> 4;
- smgWela[6]=0xf5; //0xf5是小數(shù)點的位置
- return smgWela;
- }
- /*
- void ds1302_stop() //暫停ds1302
- {
- ds1302_writeData(0x8e,0x00); //清除寫保護
- ds1302_writeData(writeAddr[6],0x80); //暫停ds1302,進入超低功耗模式
- ds1302_writeData(0x8e,0x80); //使能寫保護
- } */
- /*
- void ds1302_setUnCharger() //充電控制,禁止充電
- {
- ds1302_writeData(0x8e,0x00); //清除寫保護
- ds1302_writeData(0x90,0x5c); //禁止充電,降低功耗
- ds1302_writeData(0x8e,0x80); //使能寫保護
- }*/
復制代碼- #ifndef _51SMG_H_
- #define _51SMG_H_
- #include "my51.h"
- sbit dula =P2^6; //段選鎖存器控制 控制筆段
- sbit wela =P2^7; //位選鎖存器控制 控制位置
- extern u8 data smgWela[7]; //第一位到第六位,最后一個是小數(shù)點位置控制
- #define dark 0x11//在段中,0x11是第17號元素,0x00是低電平,數(shù)碼管不亮,即table[17]
- #define dotDark 0xff//小數(shù)點全暗
- void displaySMG(u8* pWela); //數(shù)碼管顯示函數(shù),參數(shù)是數(shù)組指針
- #endif
復制代碼
- #include "smg.h"
- #include "my51.h"
- static u8 code table[]= { //0~F外加小數(shù)點和空輸出的數(shù)碼管編碼
- 0x3f , 0x06 , 0x5b , 0x4f , // 0 1 2 3
- 0x66 , 0x6d , 0x7d , 0x07 , // 4 5 6 7
- 0x7f , 0x6f , 0x77 , 0x7c , // 8 9 A B
- 0x39 , 0x5e , 0x79 , 0x71 , // C D E F
- 0x80 , 0x00 ,0x40 // . 空 負號 空為第17號元素
- };
- /* 由于此表只能一次顯示一個小數(shù)點,故已注釋掉,僅供查詢
- 例如想要第一個和第六個數(shù)碼管小數(shù)點同時點亮,
- 則執(zhí)行 pWela->dot = 0xfe & 0xdf 即可
- u8 code dotTable[]={ //小數(shù)點位置,某一位置0時,小數(shù)點亮
- 0xff , //全暗
- 0xfe , 0xfd , 0xfb , //1 2 3
- 0xf7 , 0xef , 0xdf //4 5 6
- };*/
- u8 data smgWela[7]={0,0,0,0,0,0,0}; //第一位到第六位,最后一個是小數(shù)點位置控制
- //P0口的數(shù)碼管位選控制鎖存器只用了低6位,我們保留高2位的數(shù)據(jù),留作它用
- void displaySMG(u8* pWela)
- {
- u8 i=0;
- //控制6位數(shù)碼管顯示函數(shù),不顯示的位用參數(shù)dark
- u8 preState=P0|0x3f; //保存高2位狀態(tài),其中最高位是ADC0804的片選信號
- wela=0;dula=0;_nop_();//先鎖定數(shù)據(jù),防止吳亮及位選鎖存器高2位數(shù)據(jù)被改變
-
- P0=0; //由于數(shù)碼管是共陰極的,陽極送低電平,燈不亮
- dula=1;_nop_();
- dula=0; //段選數(shù)據(jù)清空并鎖定
- P0=preState; //共陰極數(shù)碼管是陰極置高不亮,低6位置1,高2位保留
- wela=1;_nop_(); //注:wela和dula上電默認為1
- wela=0; //位選鎖定,初始保留高2位的數(shù)據(jù),低6位置高不亮
- for(i=0;i<6;i++) //顯示6位數(shù)碼管
- {
- P0=table[pWela[i]]|(((1<<i) &="" pwela[6])?0x00:0x80);
- dula=1;_nop_(); //送段數(shù)據(jù),疊加小數(shù)點的顯示,0x00點亮小數(shù)點
- dula=0;
-
- P0=preState&~(1<<i); 不影響高2位數(shù)據(jù),低6位是數(shù)碼管位選,低電平有效
- wela=1; _nop_(); //送位選號
- wela=0;
- delayms(1); //稍作延時,讓燈管亮起來
- { //消除疊影及誤亮,陰極置1不亮,低6位置1,高2位保留并鎖定
- P0=preState;
- wela=1; _nop_();
- wela=0;
- }
- }
- }
復制代碼
|
|