1. 程式人生 > >【藍橋杯微控制器組】實時時鐘RTC(DS1302)

【藍橋杯微控制器組】實時時鐘RTC(DS1302)

1、暫存器表


注意:

(1)ds1302.h中提供的暫存器地址是寫地址,讀暫存器時需要將地址加一

(2)

#define ds1302_control_addr		0x8Ee		//防寫命令字單元地址
對應上圖倒數第二行:BIT7 = 0(取消防寫)、BIT7 = 1(上防寫)
(3)讀一次暫存器後需要增加一條寫指令(不知道為什麼):
curtime[i] = Ds1302_Single_Byte_Read(read_addr[i]);
Ds1302_Single_Byte_Write(0x00, 0x00);	
(4)在提供的ds1302.c中使用到的函式為:
/********************************************************************/ 
/*向DS1302單位元組寫入一位元組資料*/
extern void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat);
/********************************************************************/ 
/*從DS1302單位元組讀出一位元組資料*/
extern unsigned char Ds1302_Single_Byte_Read(unsigned char addr);

2、DS1302相關知識(from datasheet):


X1、X2:32.768KHZ晶振

SCLK:序列時鐘

CE:復位腳,在資料讀寫期間必須為高

I/O:資料

兩電源引腳關係為備用電源,Vcc1為主電源

CLK I/O經常與I2C匯流排接在一個引腳上,但DS1302並不是I2C匯流排,是一種三線式匯流排

3、DS1302驅動分析(比賽提供)

驅動步驟:

(1)CE  = 1

(2)在上升沿按位傳輸地址字

(3)讀取 / 寫入相應地址的資料

(4)CE = 0

附:驅動檔案ds1302.c

/********************************************************************/ 
/*向DS1302 單位元組寫入一位元組資料*/
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat)
{ 

	RST_CLR;			/*RST腳置低,實現DS1302的初始化*/
	SCK_CLR;			/*SCK腳置低,實現DS1302的初始化*/

	RST_SET;			/*啟動DS1302匯流排,RST=1電平置高 */
	addr = addr & 0xFE;	 
	Write_Ds1302_Byte(addr); /*寫入目標地址:addr,保證是寫操作,寫之前將最低位置零*/	
	Write_Ds1302_Byte(dat);	 /*寫入資料:dat*/
	RST_CLR;				 /*停止DS1302匯流排*/
}

/********************************************************************/ 
/*從DS1302單位元組讀出一位元組資料*/
unsigned char Ds1302_Single_Byte_Read(unsigned char addr) 
{ 
	unsigned char temp;
	RST_CLR;			/*RST腳置低,實現DS1302的初始化*/
	SCK_CLR;			/*SCK腳置低,實現DS1302的初始化*/

	RST_SET;	/*啟動DS1302匯流排,RST=1電平置高 */	
	addr = addr | 0x01;	 
	Write_Ds1302_Byte(addr); /*寫入目標地址:addr,保證是讀操作,寫之前將最低位置高*/
	temp=Read_Ds1302_Byte(); /*從DS1302中讀出一個位元組的資料*/		
	RST_CLR;	/*停止DS1302匯流排*/
	return temp;
}


4、設定 / 讀取時間

(1)設定時間

uchar settime[6] = {1,11,22,17,20,0};

uchar write_addr[6] = {0x8C,0x88,0x86,0x84,0x82,0x80};
uchar read_addr[6] = {0x8d,0x89,0x87,0x85,0x83,0x81};

void DS1302_settime(uchar stime[])			//輸入十進位制數字
{
	uchar temptime[6];
	int i;
	for(i = 0;i < 6;i++)  					//按暫存器格式整理輸入資料
	{
		temptime[i] = ((stime[i]/10)<<4)+(stime[i]%10);
	}
	Ds1302_Single_Byte_Write(ds1302_control_addr, 0x00); 	//取消防寫
	for(i=0;i<6;i++)
	{
		Ds1302_Single_Byte_Write(write_addr[i], temptime[i]);//設定時間	
	}
	Ds1302_Single_Byte_Write(ds1302_control_addr, 0x80); 	//上防寫
}

注意:為了方便起見,將用到的暫存器地址位放入陣列,取值參照ds1302.h,read_addr = write_addr + 1

(2)獲取時間

uchar curtime[6];

void gettime()									//輸出十進位制數字
{
	int i;
	for(i=0;i<6;i++)
	{	
		curtime[i] = Ds1302_Single_Byte_Read(read_addr[i]);
		Ds1302_Single_Byte_Write(0x00, 0x00);	
		curtime[i] = ((curtime[i] & 0xf0)>>4)*10+(curtime[i] & 0x0f);
	}	
}

附:測試程式

void main()
{
	cls_buzz();
	UartInit();

	DS1302_settime(settime);

	Delay100ms(100);
	gettime();
	sendtime(curtime);

	while(1);
}

void sendtime(char dat[])
{
	int i;
	for(i=0;i<6;i++)
	{
		SBUF = 	dat[i];
		while(!TI);
		TI = 0;
	}

}