【藍橋杯單片機12】實時時鐘DS1302的基本操做數組
www.xmf393.com / 廣東職業技術學院 歐浩源性能
實時時鐘DS1302幾乎是藍橋杯「單片機設計與開發」每一年必考的內容,雖然在競賽現場有提供一個底層讀寫寄存器的庫文件,可是做爲備賽階段,你應該搞清楚底層讀寫時序的代碼實現。你會使用庫文件開發,不必定會本身寫底層;你會本身寫驅動,就必定會使用庫文件開發。你使用庫文件開發的過程當中碰到問題,或者須要調整時序的時候,若是沒有過硬的功夫,那隻能懵逼了。spa
一、什麼是DS1302?
DS1302是美國DALLAS公司推出的高性能、低功耗的實時時鐘,附加31字節的靜態RAM,採用SP三線接口與MCU進行同步通訊,並可採用突發方式一次傳送多個字節的時鐘參數和RAM數據。實時時鐘可提供秒、分、時、日、星期、月和年,一個月小於31天時能夠自動調整,並具備潤年補償功能。
簡單來講,DS1302能夠理解爲一個電子手表,裏面帶有一個31字節的內存。固然,基本的使用方法和咱們平時使用電子手錶差很少,你能夠設定時間,也能夠讀取時間,只不過這些工做是經過SPI接口有MCU去完成而已。
在DS1302中有兩塊存儲器:日曆時鐘寄存器和今天RAM存儲器。前者用於記錄實時時間,後者用於記錄其餘數據。對於基本計時應用,重點關注的是日曆時鐘寄存器。設定時間參數就是往這些寄存器寫入內容,讀取實時時間也是從這些寄存器讀出數據。設計
二、日曆時鐘寄存器
DS1302有關日曆和時鐘的寄存器有12個,咱們最經常使用的有7個。3d
什麼是BCD碼?
就是用十六進制來表示十進制。什麼意思?怎麼理解?
例如,十六進制數0x13的值爲整數19,但BCD碼錶示的是整數13。code
三、控制字的格式
DS1302將地址和讀寫控制放到一個字節裏面,造成一個控制字,格式以下:blog
經過上面的控制字格式,你們就能夠明白爲何DS1302讀寄存器和寫寄存器的地址是不同的了,由於這個地址包含了讀寫控制位。爲了方便程序設計,咱們把讀寄存器地址、寫寄存器地址和日曆時鐘寄存器方面用三個數組定義。接口
四、接口時序的實現
DS1302的基本操做實際上很是簡單,只有兩個操做:其一是設定時間參數,其二是讀取實時時間。無論是那個操做,MCU都要經過SPI接口進行數據交互,而SPI接口有其規定的時序,這個必須參考數據手冊。
控制字總是從最低位開始輸出。在控制字指令輸入後的下一個SCLK時鐘信號的上升沿,數據被寫入DS1302,數據的輸入從最低位開始;在控制字指令輸入後的下一個SCLK時鐘信號的降低沿,數據從DS1302讀出,數據的讀出也是從最低位到最高位。
<1> 單字節寫的時序內存
底層驅動代碼實現可參考以下:開發
void DS1302_WriteByte(unsigned char addr, unsigned char dat) { unsigned char n; RST = 0; _nop_(); SCLK = 0; _nop_(); RST = 1; _nop_(); for (n=0; n<8; n++) //發送要寫入數據的內存地址 { DSIO = addr & 0x01; addr >>= 1; SCLK = 1; _nop_(); SCLK = 0; _nop_(); } for (n=0; n<8; n++) //將指定內容寫入該地址的內存 { DSIO = dat & 0x01; dat >>= 1; SCLK = 1; _nop_(); SCLK = 0; _nop_(); } RST = 0; _nop_(); }
<2> 單字節讀的時序
底層驅動代碼實現可參考以下:
unsigned char DS1302_ReadByte(unsigned char addr) { unsigned char n,dat,tmp; RST = 0; _nop_(); SCLK = 0; _nop_(); RST = 1; _nop_(); for(n=0; n<8; n++) //發送要讀出數據的內存地址 { DSIO = addr & 0x01; addr >>= 1; SCLK = 1; _nop_(); SCLK = 0; _nop_(); } for(n=0; n<8; n++) //讀出該地址內存的數據 { tmp = DSIO; dat = (dat>>1) | (tmp<<7); SCLK = 1; _nop_(); SCLK = 0; _nop_(); } RST = 0; _nop_(); SCLK = 1; _nop_(); DSIO = 0; _nop_(); DSIO = 1; _nop_(); return dat; }
有了上面兩個底層的SPI接口數據讀寫代碼,那麼DS1302的基本操做就很容易實現了。
五、單元實訓題目
六、實現源碼參考
#include "reg52.h" #include "intrins.h" sbit HC138_A = P2^5; sbit HC138_B = P2^6; sbit HC138_C = P2^7; sbit SCLK = P1^7; sbit RST = P1^3; sbit DSIO = P2^3; unsigned char code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; unsigned char code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c}; unsigned char TIME[7] = {0x30, 0x50, 0x23, 0x17, 0x02, 0x06, 0x18}; unsigned char code SMG_NoDot[18] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e, 0xbf,0x7f}; void DelaySMG(unsigned int time) { while(time--); } void Init74HC138(unsigned char n) { switch(n) { case 4: HC138_A = 0; HC138_B = 0; HC138_C = 1; break; case 5: HC138_A = 1; HC138_B = 0; HC138_C = 1; break; case 6: HC138_A = 0; HC138_B = 1; HC138_C = 1; break; case 7: HC138_A = 1; HC138_B = 1; HC138_C = 1; break; case 8: HC138_A = 0; HC138_B = 0; HC138_C = 0; break; } } void DispaySMG_Bit(unsigned char value, unsigned char pos) { Init74HC138(6); P0 = (0x01 << pos); Init74HC138(7); P0 = value; } void DS1302_WriteByte(unsigned char addr, unsigned char dat) { unsigned char n; RST = 0; _nop_(); SCLK = 0; _nop_(); RST = 1; _nop_(); for (n=0; n<8; n++) { DSIO = addr & 0x01; addr >>= 1; SCLK = 1; _nop_(); SCLK = 0; _nop_(); } for (n=0; n<8; n++) { DSIO = dat & 0x01; dat >>= 1; SCLK = 1; _nop_(); SCLK = 0; _nop_(); } RST = 0; _nop_(); } unsigned char DS1302_ReadByte(unsigned char addr) { unsigned char n,dat,tmp; RST = 0; _nop_(); SCLK = 0; _nop_(); RST = 1; _nop_(); for(n=0; n<8; n++) { DSIO = addr & 0x01; addr >>= 1; SCLK = 1; _nop_(); SCLK = 0; _nop_(); } for(n=0; n<8; n++) { tmp = DSIO; dat = (dat>>1) | (tmp<<7); SCLK = 1; _nop_(); SCLK = 0; _nop_(); } RST = 0; _nop_(); SCLK = 1; _nop_(); DSIO = 0; _nop_(); DSIO = 1; _nop_(); return dat; } void DS1302_Config() { unsigned char n; DS1302_WriteByte(0x8E,0x00); for (n=0; n<7; n++) { DS1302_WriteByte(WRITE_RTC_ADDR[n],TIME[n]); } DS1302_WriteByte(0x8E,0x80); } void DS1302_ReadTime() { unsigned char n; for (n=0; n<7; n++) { TIME[n] = DS1302_ReadByte(READ_RTC_ADDR[n]); } } void XMF_ShowRealTime() { DispaySMG_Bit(SMG_NoDot[TIME[2]/16],0); DelaySMG(500); DispaySMG_Bit(0xff,0); DispaySMG_Bit(SMG_NoDot[TIME[2]&0x0f],1); DelaySMG(500); DispaySMG_Bit(0xff,1); DispaySMG_Bit(SMG_NoDot[16],2); DelaySMG(500); DispaySMG_Bit(0xff,2); DispaySMG_Bit(SMG_NoDot[TIME[1]/16],3); DelaySMG(500); DispaySMG_Bit(0xff,3); DispaySMG_Bit(SMG_NoDot[TIME[1]&0x0f],4); DelaySMG(500); DispaySMG_Bit(0xff,4); DispaySMG_Bit(SMG_NoDot[16],5); DelaySMG(500); DispaySMG_Bit(0xff,5); DispaySMG_Bit(SMG_NoDot[TIME[0]/16],6); DelaySMG(500); DispaySMG_Bit(0xff,6); DispaySMG_Bit(SMG_NoDot[TIME[0]&0x0f],7); DelaySMG(500); DispaySMG_Bit(0xff,7); } main() { DS1302_Config(); while(1) { DS1302_ReadTime(); XMF_ShowRealTime(); } }