1. 程式人生 > >20141108 【 微控制器——萬年曆DS1302——中斷 】 用DS1302模組 & 數碼管顯示萬年曆

20141108 【 微控制器——萬年曆DS1302——中斷 】 用DS1302模組 & 數碼管顯示萬年曆

不得不說,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;
}

*/