程序代碼由3個文件組成,main.c,DS1302.c,DS1302.h。
1. main.c
/************************************************************************************* * 實驗現象: 實時時間顯示及調節 * 接線說明: 動態數碼管段選接P0,位選接P2^2,3,4口,k1、k2、k3、k4接P3^1、0、2、3,beep接P1^5 ************************************************************************************** */ #include "reg52.h" //此文件中定義了單片機的一些特殊功能寄存器 #include "ds1302.h" typedef unsigned int u16; //對數據類型進行聲明定義 typedef unsigned char u8; sbit LSA = P2 ^ 2; sbit LSB = P2 ^ 3; sbit LSC = P2 ^ 4; sbit k1 = P3 ^ 1; sbit k2 = P3 ^ 0; sbit k3 = P3 ^ 2; sbit k4 = P3 ^ 3; sbit beep = P1 ^ 5; char num = 0; u8 DisplayData[8]; u8 code smgduan[20] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71, 0x00, 0x40}; //顯示0~F,無,'-'的值 u8 clocks, minutes, seconds; u8 stopSwitch = 0; u8 beepSwitch = 0; /******************************************************************************* * 函 數 名 : delay() * 函數功能 : 延時函數,i=1時,大約延時10us *******************************************************************************/ void delay(u16 i) { while (i--) ; } /******************************************************************************* * 函 數 名 : DS1302WriteTime() * 函數功能 : 時分秒寫入函數 * 輸 入 : 時、分、秒 * 輸 出 : 無 *******************************************************************************/ void DS1302WriteTime(u8 clocks, u8 minutes, u8 seconds) { u8 clocks_16, minutes_16, seconds_16; clocks_16 = (clocks / 10 * 16) | (clocks % 10); minutes_16 = (minutes / 10 * 16) | (minutes % 10); seconds_16 = (seconds / 10 * 16) | (seconds % 10); Ds1302Write(0x8E, 0X00); //禁止寫保護,就是關閉寫保護功能 Ds1302Write(WRITE_RTC_ADDR[2], clocks_16); Ds1302Write(WRITE_RTC_ADDR[1], minutes_16); Ds1302Write(WRITE_RTC_ADDR[0], seconds_16); Ds1302Write(0x8E, 0x80); //打開寫保護功能 } /******************************************************************************* * 函 數 名 : getTime() * 函數功能 : 時間讀取處理轉換函數 * 輸 入 : 無 * 輸 出 : 無 *******************************************************************************/ void getTime() { if (stopSwitch) { DS1302WriteTime(clocks, minutes, seconds); } else { Ds1302ReadTime(); clocks = (TIME[2] / 16 * 10) + (TIME[2] % 16); minutes = (TIME[1] / 16 * 10) + (TIME[1] % 16); seconds = (TIME[0] / 16 * 10) + (TIME[0] % 16); } } /******************************************************************************* * 函 數 名 : DigDisplay * 函數功能 : 數碼管顯示函數 * 參數 : ord為數碼管次序,ch為該數碼管顯示符號 *******************************************************************************/ void DigDisplay(u8 ord, u8 ch) { switch (ord) //位選,選擇點亮的數碼管, { case (0): LSA = 1; LSB = 1; LSC = 1; break; //顯示第0位 case (1): LSA = 0; LSB = 1; LSC = 1; break; //顯示第1位 case (2): LSA = 1; LSB = 0; LSC = 1; break; //顯示第2位 case (3): LSA = 0; LSB = 0; LSC = 1; break; //顯示第3位 case (4): LSA = 1; LSB = 1; LSC = 0; break; //顯示第4位 case (5): LSA = 0; LSB = 1; LSC = 0; break; //顯示第5位 case (6): LSA = 1; LSB = 0; LSC = 0; break; //顯示第6位 case (7): LSA = 0; LSB = 0; LSC = 0; break; //顯示第7位 } P0 = smgduan[ch]; //發送段碼 if (beepSwitch) beep = ~beep; } /******************************************************************************* * 函 數 名 : timeDisplay * 函數功能 : 將時分秒顯示在數碼管上 * 輸 入 : 無 * 輸 出 : 無 *******************************************************************************/ void timeDisplay() { u8 n = 0; u8 dig[10]; getTime(); dig[0] = clocks / 10; dig[1] = clocks % 10; dig[2] = 17; dig[3] = minutes / 10; dig[4] = minutes % 10; dig[5] = 17; dig[6] = seconds / 10; dig[7] = seconds % 10; for (n = 0; n < 8; n++) { DigDisplay(n, dig[n]); delay(10); DigDisplay(n, 16); } } /******************************************************************************* * 函 數 名 : keypros * 函數功能 : 按鍵處理 * 輸 入 : 無 * 輸 出 : 無 *******************************************************************************/ void keypros() { u16 delayTimes = 10; //按鍵K1 if (k1 == 0) //檢測按鍵K1是否按下 { while (delayTimes--) timeDisplay(); //消除抖動 一般大約10ms if (k1 == 0) //再次判斷按鍵是否按下 { if (++clocks == 24) { clocks = 0; } DS1302WriteTime(clocks, minutes, seconds); } while (!k1) timeDisplay(); //檢測按鍵是否松開 } //按鍵K2 if (k2 == 0) //檢測按鍵是否按下 { while (delayTimes--) timeDisplay(); //消除抖動 一般大約10ms if (k2 == 0) //再次判斷按鍵是否按下 { if (++minutes == 60) { minutes = 0; } DS1302WriteTime(clocks, minutes, seconds); } while (!k2) timeDisplay(); //檢測按鍵是否松開 } //按鍵K3 if (k3 == 0) //檢測按鍵是否按下 { while (delayTimes--) timeDisplay(); //消除抖動 一般大約10ms if (k3 == 0) //再次判斷按鍵是否按下 { if (++seconds == 60) { seconds = 0; } DS1302WriteTime(clocks, minutes, seconds); } while (!k3) timeDisplay(); //檢測按鍵是否松開 } //按鍵K4 if (k4 == 0) //檢測按鍵是否按下 { while (delayTimes--) timeDisplay(); //消除抖動 一般大約10ms if (k4 == 0) //再次判斷按鍵是否按下 { stopSwitch = (stopSwitch + 1) % 2; } while (!k4) timeDisplay(); //檢測按鍵是否松開 } } /******************************************************************************* * 函 數 名 : main * 函數功能 : 主函數 * 輸 入 : 無 * 輸 出 : 無 *******************************************************************************/ void main() { Ds1302Init(); //初始化 while (1) { keypros(); //按鍵處理 timeDisplay(); //顯示時間 //蜂鳴器整點響應 if (minutes == 59 && seconds == 59) { beepSwitch = 1; } if (beepSwitch == 1) { if (minutes == 0 && seconds == 3) { beepSwitch = 0; } } } }
2. ds1302.h
#ifndef __DS1302_H_ #define __DS1302_H_ //---包含頭文件---// #include<reg52.h> #include<intrins.h> //---重定義關鍵詞---// #ifndef uchar #define uchar unsigned char #endif #ifndef uint #define uint unsigned int #endif //---定義ds1302使用的IO口---// sbit DSIO=P3^4; sbit RST=P3^5; sbit SCLK=P3^6; //---定義全局函數---// void Ds1302Write(uchar addr, uchar dat); uchar Ds1302Read(uchar addr); void Ds1302Init(); void Ds1302ReadTime(); //---加入全局變量--// extern uchar TIME[7]; //加入全局變量 extern uchar code WRITE_RTC_ADDR[7]; #endif
3. ds1302.c
#include"ds1302.h" //---DS1302寫入和讀取時分秒的地址命令---// //---秒分時日月周年 最低位讀寫位;-------// uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c}; //---DS1302時鍾初始化2016年5月7日星期六12點00分00秒。---// //---存儲順序是秒分時日月周年,存儲格式是用BCD碼---// uchar TIME[7] = {0, 0, 0x12, 0x07, 0x05, 0x06, 0x16}; /******************************************************************************* * 函 數 名 : Ds1302Write * 函數功能 : 向DS1302命令(地址+數據) * 輸 入 : addr,dat * 輸 出 : 無 *******************************************************************************/ void Ds1302Write(uchar addr, uchar dat) { uchar n; RST = 0; _nop_(); SCLK = 0;//先將SCLK置低電平。 _nop_(); RST = 1; //然后將RST(CE)置高電平。 _nop_(); for (n=0; n<8; n++)//開始傳送八位地址命令 { DSIO = addr & 0x01;//數據從低位開始傳送 addr >>= 1; SCLK = 1;//數據在上升沿時,DS1302讀取數據 _nop_(); SCLK = 0; _nop_(); } for (n=0; n<8; n++)//寫入8位數據 { DSIO = dat & 0x01; dat >>= 1; SCLK = 1;//數據在上升沿時,DS1302讀取數據 _nop_(); SCLK = 0; _nop_(); } RST = 0;//傳送數據結束 _nop_(); } /******************************************************************************* * 函 數 名 : Ds1302Read * 函數功能 : 讀取一個地址的數據 * 輸 入 : addr * 輸 出 : dat *******************************************************************************/ uchar Ds1302Read(uchar addr) { uchar n,dat,dat1; RST = 0; _nop_(); SCLK = 0;//先將SCLK置低電平。 _nop_(); RST = 1;//然后將RST(CE)置高電平。 _nop_(); for(n=0; n<8; n++)//開始傳送八位地址命令 { DSIO = addr & 0x01;//數據從低位開始傳送 addr >>= 1; SCLK = 1;//數據在上升沿時,DS1302讀取數據 _nop_(); SCLK = 0;//DS1302下降沿時,放置數據 _nop_(); } _nop_(); for(n=0; n<8; n++)//讀取8位數據 { dat1 = DSIO;//從最低位開始接收 dat = (dat>>1) | (dat1<<7); SCLK = 1; _nop_(); SCLK = 0;//DS1302下降沿時,放置數據 _nop_(); } RST = 0; _nop_(); //以下為DS1302復位的穩定時間,必須的。 SCLK = 1; _nop_(); DSIO = 0; _nop_(); DSIO = 1; _nop_(); return dat; } /******************************************************************************* * 函 數 名 : Ds1302Init * 函數功能 : 初始化DS1302. * 輸 入 : 無 * 輸 出 : 無 *******************************************************************************/ void Ds1302Init() { uchar n; Ds1302Write(0x8E,0X00); //禁止寫保護,就是關閉寫保護功能 for (n=0; n<7; n++)//寫入7個字節的時鍾信號:分秒時日月周年 { Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]); } Ds1302Write(0x8E,0x80); //打開寫保護功能 } /******************************************************************************* * 函 數 名 : Ds1302ReadTime * 函數功能 : 讀取時鍾信息 * 輸 入 : 無 * 輸 出 : 無 *******************************************************************************/ void Ds1302ReadTime() { uchar n; for (n=0; n<7; n++)//讀取7個字節的時鍾信號:分秒時日月周年 { TIME[n] = Ds1302Read(READ_RTC_ADDR[n]); } }