20141108 【 微控制器——萬年曆DS1302——中斷 】 用DS1302模組 & 數碼管顯示萬年曆
阿新 • • 發佈:2019-01-03
不得不說,DS1302的介面規則挺麻煩的,不查規格書不好用啊。
【我是菜鳥,感覺就算是大神,也不會揹著玩意吧。。】
8個八段數碼管顯示:
【1】 星期 . 上午下午 . 小時 . 分鐘 . 秒鐘
【2】 年份 . 月份 . 天數
10/11的時間顯示 狀態【1】:星期(佔1,顯示1~7),上午下午(佔1,顯示“A”或“P”),小時(佔2,十二小時制顯示00~12),分鐘(佔2,顯示00~59),秒鐘(佔2,顯示00~59)。
1/11的時間顯示 狀態【2】:年份(佔4,顯示2000~2099),月份(佔2,顯示1~12),天數(佔2,顯示00~day[ 平年/閏年+月份 ])。
戰果:
搞了老半天,最終還是跪在 DS1302的讀寫函式 上。
最後面把標程的 DS1302的讀寫函式 拷貝來用,就成了。
【原來的 DS1302讀寫函式 在下面程式碼的註釋區那裡,有空再查吧!!】
#include <reg52.h> #include <intrins.h> #define uint unsigned int #define uchar unsigned char #define DIGIT_MAX 16 #define LCD P0 #define LCD_BIN P2 const uchar digital[DIGIT_MAX+5] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x80}; // 0123456789 AbCdEF. + 17 const uchar digital_bin[8] = {0xE3, 0xE7, 0xEB, 0xEF, 0xF3, 0xF7, 0xFB, 0xFF}; //{0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C}; const uint TIME_H = (65536 - 9174)/256; //0x9C; // 0x9C~100us 1000us/1.09us = 921.6 const uint TIME_L = (65536 - 9174)%256; //0x9C; uint TIME; void Timer0_int1_init(); void delay(uint dt); const uchar DS_Rbin[8] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8B, 0x8D, 0x8F}; // DS1302 Read-register const uchar DS_Wbin[8] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8E}; // DS1302 Write-register sbit SCLK = P3^6; sbit DSIO = P3^4; //IO sbit RST = P3^5; //CE uchar LCD_CHOOSE; void DS1302_write(uchar addr, uchar dat) { uchar n; EA = 0; 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_(); EA = 1; } uchar DS1302_read(uchar addr) { uchar n,dat,dat1; EA =0; 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_(); EA = 1; return dat; } uchar DS_dat[8] = {0x00, 0x30, 0xB1, 0x01, 0x11, 0x12, 0x00}; // second - minth - hour[A/P] - day - month - weeken - year - protect uchar LCD_now[8]; void DS1302_init(){ uchar i; DS1302_write(DS_Wbin[7], 0x00); for(i=0; i<7; i++){ DS1302_write(DS_Wbin[i], DS_dat[i]); } DS1302_write(DS_Wbin[7], 0x80); } void DS1302_now(){ uchar i; for(i=0; i<7; i++) DS_dat[i] = DS1302_read( DS_Rbin[i] ); } void skip_init(); void main(){ uint i=0, cnt; skip_init(); DS1302_init(); while( 1 ){ for(cnt=10000; cnt; cnt--){ DS1302_now(); LCD_now[7] = digital[ DS_dat[0]&0x0F ]; LCD_now[6] = digital[ DS_dat[0]>>4 ]; LCD_now[5] = digital[ DS_dat[1]&0x0F ] | 0x80; LCD_now[4] = digital[ DS_dat[1]>>4 ]; LCD_now[3] = digital[ DS_dat[2]&0x0F ] | 0x80; LCD_now[2] = digital[ (DS_dat[2]>>4)&1 ]; LCD_now[1] = DS_dat[2]&0x20 ? 0xF7 : 0xF3; LCD_now[0] = digital[ DS_dat[5]&0x0F ] | 0x80; } for(cnt=1000; cnt; cnt--) { DS1302_now(); LCD_now[7] = digital[ DS_dat[3]&0x0F ]; LCD_now[6] = digital[ DS_dat[3]>>4 ]; LCD_now[5] = digital[ DS_dat[4]&0x0F ] | 0x80; LCD_now[4] = digital[ DS_dat[4]>>4 ]; LCD_now[3] = digital[ DS_dat[6]&0x0F ] | 0x80; LCD_now[2] = digital[ DS_dat[6]>>4 ]; LCD_now[1] = 0x3F; LCD_now[0] = 0x5B; } } } void skip_init(){ TMOD = 0x02; //定時器模式 TH0 = TIME_H; TL0 = TIME_L; EA = 1; ET0 = 1; TR0 = 1; } void skip() interrupt 1{ LCD = 0x00; LCD_BIN = digital_bin[ 7-LCD_CHOOSE ]; LCD = LCD_now[ LCD_CHOOSE ]; LCD_CHOOSE = ( ++LCD_CHOOSE )&0x07; } /* uchar DS1302_read(uchar addr){ uchar i, res; EA = 0; RST = 0; _nop_(); SCLK = 0; _nop_(); RST = 1; _nop_(); for(i=0; i<8; i++){ DSIO = (addr>>i) & 0x01; SCLK=1; _nop_(); //DS1302 讀資料 SCLK=0; _nop_(); //DS1302 存資料 } _nop_(); for(i=7; i>=0; i--){ res |= (uchar)DSIO<<i; SCLK=1; _nop_(); //DS1302 讀資料 SCLK=0; _nop_(); //DS1302 存資料 } RST = 0; _nop_(); //下面 DS1302復位的穩定時間,必須的。 SCLK = 1; _nop_(); DSIO = 0; _nop_(); DSIO = 1; _nop_(); EA = 1; return res; } void DS1302_write(uchar addr, uint dat){ uchar i; EA = 0; SCLK = 0; _nop_(); RST = 1; _nop_(); for(i=0; i<8; i++){ DSIO = (addr>>i)&0x01; SCLK=1; _nop_(); SCLK=0; _nop_(); } for(i=0; i<8; i++){ DSIO = (dat>>i) & 0x01; SCLK=1; _nop_(); SCLK=0; _nop_(); } RST = 0; _nop_(); //資料傳輸完畢 EA = 1; } */