一、前言
今天給大家推薦一個(gè)51單片機(jī)小實(shí)驗(yàn),帶你使用51單片機(jī)做一款簡(jiǎn)易的電子時(shí)鐘,其中計(jì)時(shí)模塊采用DS1302硬件模塊,顯示采用LCD顯示屏,具體怎么實(shí)現(xiàn)開(kāi)來(lái)一起看看吧!
二、DS1302模塊介紹
DS1302 是 DALLAS 公司推出的涓流充電時(shí)鐘芯片,內(nèi)含有一個(gè)實(shí)時(shí)時(shí)鐘和31字節(jié)靜態(tài) RAM,通過(guò)簡(jiǎn)單的串行接口與單片機(jī)進(jìn)行通信。實(shí)時(shí)時(shí)鐘、日歷電路提供秒、分、時(shí)、日、周、月、年的信息,每月的天數(shù)和閏年自動(dòng)補(bǔ)償?shù)榷喾N功能。時(shí)鐘操作可通過(guò) AM/PM 指示,DS1302 與單片機(jī)之間能簡(jiǎn)單地采用同步串行的方式進(jìn)行通信,簡(jiǎn)易三線(xiàn)SPI通信模式:
RES 復(fù)位
I/O 數(shù)據(jù)線(xiàn)
SCLK 串行時(shí)鐘
SPI,是一種高速的,全雙工,同步的通信總線(xiàn),并且在芯片的管腳上只占用四根線(xiàn),節(jié)約了芯片的管腳,同時(shí)為PCB的布局上節(jié)省空間,提供方便,正是出于這種簡(jiǎn)單易用的特性,現(xiàn)在越來(lái)越多的芯片集成了這種通信協(xié)議,比如MSP430單片機(jī)系列處理器。
DS1302時(shí)鐘芯片的工作原理如下:
DS1302芯片內(nèi)部有一組定時(shí)器和寄存器,通過(guò)這些寄存器可以實(shí)現(xiàn)時(shí)鐘的讀寫(xiě)操作。
DS1302通過(guò)三根引腳與外部設(shè)備連接,分別是RST、DAT和CLK。RST引腳用于復(fù)位
DS1302,DAT引腳用于數(shù)據(jù)傳輸,CLK引腳用于時(shí)鐘信號(hào)。
DS1302芯片使用BCD碼表示時(shí)間信息,即用4位二進(jìn)制數(shù)表示一個(gè)十進(jìn)制數(shù)。例如,分的BCD碼為00H到59H。
三、驅(qū)動(dòng)DS1302的代碼
以下是使用51單片機(jī)驅(qū)動(dòng)DS1302時(shí)鐘芯片的代碼,具體實(shí)現(xiàn)步驟如下:
3.1 初始化DS1302時(shí)鐘芯片
voidDS1302Init(){ //初始化DS1302時(shí)鐘芯片 DS1302WriteByte(0x8E,0x00); //關(guān)閉寫(xiě)保護(hù) DS1302WriteByte(0x90,0x00); }
3.2 讀取DS1302時(shí)鐘芯片的時(shí)間
voidDS1302ReadTime(unsignedchar*p){ //讀取DS1302時(shí)鐘芯片的時(shí)間 unsignedchari; DS1302WriteByte(0xBF,0x00); for(i=0;i7;?i++)?{ ????????p[i]?=?DS1302ReadByte(); ????} }
3.3 設(shè)置DS1302時(shí)鐘芯片的時(shí)間
voidDS1302WriteTime(unsignedchar*p){ //設(shè)置DS1302時(shí)鐘芯片的時(shí)間 unsignedchari; DS1302WriteByte(0xBE,0x00); for(i=0;i7;?i++)?{ ????????DS1302WriteByte(p[i],?0x00); ????} }
3.4 讀取DS1302時(shí)鐘芯片的RAM
//從DS1302讀取一個(gè)字節(jié)的數(shù)據(jù) voidDS1302ReadByte(uchar*dat){ uchari; for(i=0;i8;?i++)?{ ????????SCLK?=?0; ????????_nop_(); ????????*dat?|=?IO?<
四、讀取DS1302時(shí)鐘芯片的RAM
DS1302時(shí)鐘芯片有31個(gè)字節(jié)的RAM空間,可以用來(lái)存儲(chǔ)一些數(shù)據(jù)。在實(shí)際應(yīng)用中,我們可能需要讀取這些存儲(chǔ)的數(shù)據(jù)。讀取DS1302的RAM和讀取寄存器類(lèi)似,也需要先向DS1302發(fā)送讀取RAM的命令,然后再讀取RAM的內(nèi)容。
讀取DS1302的RAM需要使用到DS1302的另一個(gè)引腳——CE(片選使能)引腳,該引腳在讀寫(xiě)DS1302的RAM時(shí)需要保持為低電平。讀取RAM的過(guò)程如下:
4.1 發(fā)送讀取RAM的命令
向DS1302寫(xiě)入讀取RAM的命令:0x61。DS1302會(huì)自動(dòng)切換到RAM讀取模式,準(zhǔn)備將RAM中的數(shù)據(jù)傳輸給單片機(jī)。
DS1302Write(0x61);//發(fā)送讀取RAM命令
4.2 讀取RAM的內(nèi)容
發(fā)送讀取RAM命令后,就可以讀取RAM中的數(shù)據(jù)了。讀取RAM的數(shù)據(jù)需要先讀取DS1302的數(shù)據(jù)引腳(IO引腳)上的高電平脈沖,然后再讀取8個(gè)位的數(shù)據(jù)。具體的讀取過(guò)程可以使用DS1302ReadByte函數(shù)實(shí)現(xiàn),該函數(shù)會(huì)讀取一個(gè)字節(jié)的數(shù)據(jù)。
for(i=0;i31;?i++)?{ ????DS1302ReadByte(&byte);?//?讀取一個(gè)字節(jié)的數(shù)據(jù) ????ram[i]?=?byte;?//?存儲(chǔ)到數(shù)組中 }
讀取完RAM后,我們可以將其存儲(chǔ)到一個(gè)數(shù)組中,方便后續(xù)的使用。
4.3 讀取部分單獨(dú)代碼實(shí)現(xiàn)(注重邏輯)
#include#include #defineucharunsignedchar #defineuintunsignedint sbitSCLK=P2^0; sbitIO=P2^1; sbitCE=P2^2; uchards1302_read_ram(ucharaddress) { uchari,dat; CE=0; _nop_(); SCLK=0; _nop_(); CE=1; _nop_(); IO=0;//寫(xiě)指令 SCLK=0; _nop_(); SCLK=1; _nop_(); IO=address|0xc0;//選擇地址并讀取RAM for(i=0;i8;?i++)?{ ????????SCLK?=?0; ????????_nop_(); ????????SCLK?=?1; ????????_nop_(); ????} ????IO?=?0;?//?接收數(shù)據(jù) ????for?(i?=?0;?i?8;?i++)?{ ????????dat?>>=1; if(IO)dat|=0x80; SCLK=0; _nop_(); SCLK=1; _nop_(); } CE=0; returndat; }
在上述代碼中,ds1302_read_ram 函數(shù)接收一個(gè)參數(shù) address,用于指定要讀取的 RAM 地址,返回一個(gè)字節(jié)表示該地址處的 RAM 數(shù)據(jù)。
該函數(shù)的具體實(shí)現(xiàn)過(guò)程如下:
置 CE 為低電平,并延遲一段時(shí)間。
置 SCLK 為低電平,并延遲一段時(shí)間。
置 CE 為高電平,并延遲一段時(shí)間。
置 IO 為低電平,表示寫(xiě)指令。
置 SCLK 為低電平,并延遲一段時(shí)間。
置 SCLK 為高電平,并延遲一段時(shí)間。
置 IO 為 address | 0xc0,即選擇地址并讀取 RAM。
依次進(jìn)行 8 次時(shí)鐘上升沿,在每個(gè)上升沿時(shí)讀取數(shù)據(jù)位。
置 CE 為低電平。
返回讀取到的數(shù)據(jù)。
需要注意的是,讀取 RAM 數(shù)據(jù)時(shí)需要將地址的最高位(即 bit7)置為 1,以表示要讀取 RAM。另外,在讀取數(shù)據(jù)位時(shí)需要依次進(jìn)行 8 次時(shí)鐘上升沿,且每次讀取時(shí)需要先右移數(shù)據(jù),再將新數(shù)據(jù)左移并或上讀到的數(shù)據(jù)位。
五、整體代碼實(shí)現(xiàn)
下面是使用51單片機(jī)和DS1302時(shí)鐘芯片實(shí)現(xiàn)的簡(jiǎn)易電子時(shí)鐘的代碼實(shí)現(xiàn)。代碼中包含了DS1302的初始化、時(shí)鐘讀取、RAM讀寫(xiě)等基本功能。
#include#include"LCD1602.h" #include"DS1302.h" #defineucharunsignedchar #defineuintunsignedint sbitbeep=P3^6;//定義蜂鳴器接口 voidmain() { ucharyear,month,day,hour,minute,second;//年月日時(shí)分秒 ucharstr_data[11],str_time[11];//用于存放LCD上顯示的日期和時(shí)間 LCD_Init();//初始化LCD顯示屏 DS1302_Init();//初始化DS1302時(shí)鐘芯片 //將時(shí)間初始化為2023年2月21日0時(shí)0分0秒 DS1302_Write(0x8e,0);//關(guān)閉寫(xiě)保護(hù) DS1302_Write(0x80,0x23);//年份 DS1302_Write(0x82,0x02);//月份 DS1302_Write(0x84,0x21);//日期 DS1302_Write(0x86,0x00);//時(shí)鐘 DS1302_Write(0x88,0x00);//分鐘 DS1302_Write(0x8a,0x00);//秒鐘 DS1302_Write(0x8e,0x80);//開(kāi)啟寫(xiě)保護(hù) while(1) { //讀取DS1302時(shí)鐘芯片中的年月日時(shí)分秒 year=DS1302_Read(0x80); month=DS1302_Read(0x82); day=DS1302_Read(0x84); hour=DS1302_Read(0x86); minute=DS1302_Read(0x88); second=DS1302_Read(0x8a); //將年月日時(shí)分秒轉(zhuǎn)換成字符串 sprintf(str_data,"Data:20%02x-%02x-%02x",year,month,day); sprintf(str_time,"Time:%02x:%02x:%02x",hour,minute,second); //在LCD上顯示日期和時(shí)間 LCD_Write_String(0,0,str_data); LCD_Write_String(0,1,str_time); Delay_Ms(1000);//延時(shí)1秒 } }
六、顯示效果
審核編輯:湯梓紅
-
單片機(jī)
+關(guān)注
關(guān)注
6037文章
44558瀏覽量
635353 -
51單片機(jī)
+關(guān)注
關(guān)注
274文章
5702瀏覽量
123623 -
時(shí)鐘芯片
+關(guān)注
關(guān)注
2文章
249瀏覽量
39886 -
DS1302
+關(guān)注
關(guān)注
8文章
449瀏覽量
50695 -
電子時(shí)鐘
+關(guān)注
關(guān)注
11文章
197瀏覽量
24534
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論