【藍橋杯微控制器組】實時時鐘RTC(DS1302)
阿新 • • 發佈:2019-01-08
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;
}
}