1、DS1302芯片說明
DS1302是由美國DALLAS公司推出的具有涓細電流充電能力的低功耗實時時鐘芯片。它可以對年、月、日、周、時、分、秒進行計時,且具有閏年補償等多種功能。
P17:SCLK為時鐘輸入端。P23:I/O為串行數據輸入輸出端(雙向)
P13:RST是復位
2、日歷時鐘寄存器
(1)有關的時間寄存器:
(2)寄存器說明
第一行:秒->因為秒的范圍是0-59,所以6,5,4位表示秒的十位,3,2,1,0表示個位,十位最大是5,所以三位即可。
第二行:跟上面一樣;
第三行:7位:1為12小時制,0為24小時制;5位:12小時制時為0表示上午,1表示下午,24小時制時,和4位一起表示小時的十位;
其余的時間一樣的表示。
倒數第二行:只看7位:為WP=1時禁止寫數據,所以開始寫數據時必須置0;
3、官方提供庫文件
#include "ds1302.h"
/********************************************************************/
/*單字節寫入一字節數據*/
void Write_Ds1302_Byte(unsigned char dat)
{
unsigned char i;
SCK = 0;
for (i=0;i< 8;i++)
{
if (dat & 0x01) // 等價于if((addr & 0x01) ==1)
{
SDA_SET; //#define SDA_SET SDA=1 /*電平置高*/
}
else
{
SDA_CLR; //#define SDA_CLR SDA=0 /*電平置低*/
}
SCK_SET;
SCK_CLR;
dat = dat > > 1;
}
}
/********************************************************************/
/*單字節讀出一字節數據*/
unsigned char Read_Ds1302_Byte(void)
{
unsigned char i, dat=0;
for (i=0;i< 8;i++)
{
dat = dat > > 1;
if (SDA_R) //等價于if(SDA_R==1) #define SDA_R SDA /*電平讀取*/
{
dat |= 0x80;
}
else
{
dat &= 0x7F;
}
SCK_SET;
SCK_CLR;
}
return dat;
}
/********************************************************************/
/*向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、實時時鐘“實例一”
可以自己結合官方提供的庫文件,進行實時時鐘顯示操作。這是把官方庫文件和自己所寫的代碼結合一起,形成一個.c文件。
例:要求顯示初始值為:18—50—50,依次顯示時間。
#include< stc15f2k60s2.h >
#define uchar unsigned char
#define uint unsigned int
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST=P1^3;
uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uint f1,f2,f3,f4,f5,f6,f7,f8;
uint ReadValue1,ReadValue2,ReadValue3,hour,minute,sec;
void Write_Ds1302_Byte(unsigned char dat);
unsigned char Read_Ds1302_Byte(void);
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat);
unsigned char Ds1302_Single_Byte_Read(unsigned char addr);
void allinit();
void display12(uchar f1,uchar f2);
void display34(uchar f3,uchar f4);
void display56(uchar f5,uchar f6);
void display78(uchar f7,uchar f8);
void delay();
void main(){
allinit();
f1=11;f2=11;f3=11;f4=11;f5=11;f6=11;f7=11;f8=11;
Ds1302_Single_Byte_Write(0x8e,0x00);
Ds1302_Single_Byte_Write(0x84,((18/10)< 4|(18%10)));
Ds1302_Single_Byte_Write(0x82,((50/10)< 4|(50%10)));
Ds1302_Single_Byte_Write(0x80,((50/10)< 4|(50%10)));
Ds1302_Single_Byte_Write(0x8e,0x80);
while(1){
ReadValue1=Ds1302_Single_Byte_Read(0x85);
hour=((ReadValue1&0x70) >>4)*10+(ReadValue1&0x0f);
Ds1302_Single_Byte_Write(0x80, 0x00);
ReadValue2=Ds1302_Single_Byte_Read(0x83);
minute=((ReadValue2&0x70) >>4)*10+(ReadValue2&0x0f);
Ds1302_Single_Byte_Write(0x80, 0x00);
ReadValue3=Ds1302_Single_Byte_Read(0x81);
sec=((ReadValue3&0x70) >>4)*10+(ReadValue3&0x0f);
Ds1302_Single_Byte_Write(0x80, 0x00);
f1=hour/10;f2=hour%10;f3=10;
f4=minute/10;f5=minute%10;f6=10;
f7=sec/10;f8=sec%10;
display12(f1,f2);
display34(f3,f4);
display56(f5,f6);
display78(f7,f8);
}
}
void allinit(){
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
P2=0XC0;P0=0XFF;P2=0XFF;P0=0XFF;
}
/*單字節寫入一字節數據*/
void Write_Ds1302_Byte(unsigned char dat)
{
unsigned char i;
SCK = 0;
for (i=0;i< 8;i++)
{
if (dat & 0x01) // 等價于if((addr & 0x01) ==1)
{
SDA=1; //#define SDA_SET SDA=1 /*電平置高*/
}
else
{
SDA=0; //#define SDA_CLR SDA=0 /*電平置低*/
}
SCK=1;
SCK=0;
dat = dat > > 1;
}
}
/********************************************************************/
/*單字節讀出一字節數據*/
unsigned char Read_Ds1302_Byte(void)
{
unsigned char i, dat=0;
for (i=0;i< 8;i++)
{
dat = dat > > 1;
if (SDA) //等價于if(SDA_R==1) #define SDA_R SDA /*電平讀取*/
{
dat |= 0x80;
}
else
{
dat &= 0x7F;
}
SCK=1;
SCK=0;
}
return dat;
}
/********************************************************************/
/*向DS1302 單字節寫入一字節數據*/
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat)
{
RST=0; /*RST腳置低,實現DS1302的初始化*/
SCK=0; /*SCK腳置低,實現DS1302的初始化*/
RST=1; /*啟動DS1302總線,RST=1電平置高 */
addr = addr & 0xFE;
Write_Ds1302_Byte(addr); /*寫入目標地址:addr,保證是寫操作,寫之前將最低位置零*/
Write_Ds1302_Byte(dat); /*寫入數據:dat*/
RST=0; /*停止DS1302總線*/
}
/********************************************************************/
/*從DS1302單字節讀出一字節數據*/
unsigned char Ds1302_Single_Byte_Read(unsigned char addr)
{
unsigned char temp;
RST=0; /*RST腳置低,實現DS1302的初始化*/
SCK=0; /*SCK腳置低,實現DS1302的初始化*/
RST=1; /*啟動DS1302總線,RST=1電平置高 */
addr = addr | 0x01;
Write_Ds1302_Byte(addr); /*寫入目標地址:addr,保證是讀操作,寫之前將最低位置高*/
temp=Read_Ds1302_Byte(); /*從DS1302中讀出一個字節的數據*/
RST=0; /*停止DS1302總線*/
return temp;
}
void display12(uchar f1,uchar f2){
P2=0XC0;P0=0X01;P2=0XFF;P0=tab[f1];
delay();
P2=0XC0;P0=0X02;P2=0XFF;P0=tab[f2];
delay();
}
void display34(uchar f3,uchar f4){
P2=0XC0;P0=0X04;P2=0XFF;P0=tab[f3];
delay();
P2=0XC0;P0=0X08;P2=0XFF;P0=tab[f4];
delay();
}
void display56(uchar f5,uchar f6){
P2=0XC0;P0=0X10;P2=0XFF;P0=tab[f5];
delay();
P2=0XC0;P0=0X20;P2=0XFF;P0=tab[f6];
delay();
}
void display78(uchar f7,uchar f8){
P2=0XC0;P0=0X40;P2=0XFF;P0=tab[f7];
delay();
P2=0XC0;P0=0X80;P2=0XFF;P0=tab[f8];
delay();
}
void delay(){
int i,j;
for(i=2;i >0;i--)
for(j=600;j >0;j--);
}
結果與體會:
由于官方已經給出驅動文件,把驅動文件加以修改,在結合自己的顯示代碼,最終可以實現實時時鐘。實時時鐘部分只需要知道,如何讀時間、如何寫入初始值、轉換公式是什么。
寫入初始值操作:
Ds1302_Single_Byte_Write(0x8e,0x00);
Ds1302_Single_Byte_Write(0x84,((18/10)< 4|(18%10)));//時
Ds1302_Single_Byte_Write(0x82,((50/10)< 4|(50%10)));//分
Ds1302_Single_Byte_Write(0x80,((50/10)< 4|(50%10)));//秒
Ds1302_Single_Byte_Write(0x8e,0x80);
記著轉換公式為:((value/10)<<4|(value%10))
讀出數據操作:
ReadValue1=Ds1302_Single_Byte_Read(0x85);
hour=((ReadValue1&0x70) >>4)*10+(ReadValue1&0x0f);
Ds1302_Single_Byte_Write(0x80, 0x00);
ReadValue2=Ds1302_Single_Byte_Read(0x83);
minute=((ReadValue2&0x70) >>4)*10+(ReadValue2&0x0f);
Ds1302_Single_Byte_Write(0x80, 0x00);
ReadValue3=Ds1302_Single_Byte_Read(0x81);
sec=((ReadValue3&0x70) >>4)*10+(ReadValue3&0x0f);
Ds1302_Single_Byte_Write(0x80, 0x00);
記著轉換公式為:((ReadValue&0x70)>>4)*10+(ReadValue&0x0f)
另外寫入、讀出年、星期、月、日也是如此,只要修改寫入、讀出初始值就OK了。
5、實時時鐘“實例二”
實例一是把所有定義的函數都放到一起了,接下來的實例二,是分模塊化實現功能。兩種方法都可以實現實時時鐘,不過分模塊化更有利于修改代碼,所以對于以后多個功能的實現,分塊處理,代碼修改比較方便。
下面給出各個模塊代碼:
ds1302.c
#include "ds1302.h"
unsigned char time[]={58,58,17,0,0,0,0};
/********************************************************************/
/*單字節寫入一字節數據*/
void Write_Ds1302_Byte(unsigned char dat)
{
unsigned char i;
SCK = 0;
for (i=0;i< 8;i++)
{
if (dat & 0x01) // 等價于if((addr & 0x01) ==1)
{
SDA_SET; //#define SDA_SET SDA=1 /*電平置高*/
}
else
{
SDA_CLR; //#define SDA_CLR SDA=0 /*電平置低*/
}
SCK_SET;
SCK_CLR;
dat = dat > > 1;
}
}
/********************************************************************/
/*單字節讀出一字節數據*/
unsigned char Read_Ds1302_Byte(void)
{
unsigned char i, dat=0;
for (i=0;i< 8;i++)
{
dat = dat > > 1;
if (SDA_R) //等價于if(SDA_R==1) #define SDA_R SDA /*電平讀取*/
{
dat |= 0x80;
}
else
{
dat &= 0x7F;
}
SCK_SET;
SCK_CLR;
}
return dat;
}
/********************************************************************/
/*向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/10< 4)|(dat%10)); /*寫入數據:dat*/
RST_CLR; /*停止DS1302總線*/
}
/********************************************************************/
/*從DS1302單字節讀出一字節數據*/
unsigned char Ds1302_Single_Byte_Read(unsigned char addr)
{
unsigned char temp;
unsigned char dat1,dat2;
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中讀出一個字節的數據*/
dat1=temp/16;
dat2=temp%16;
temp=10*dat1+dat2;
//RST_CLR; /*停止DS1302總線*/
SD=0;
return temp;
}
void Ds1302_init(){
unsigned char i,add;
add=0x80;
Ds1302_Single_Byte_Write(0x8e,0x00);
for(i=0;i< 7;i++){
Ds1302_Single_Byte_Write(add,time[i]);
add+=2;
}
Ds1302_Single_Byte_Write(0x8e,0x80);
}
void Ds1302_Gettime(){
unsigned char i,add;
add=0x81;
Ds1302_Single_Byte_Write(0x8e,0x00);
for(i=0;i< 7;i++){
time[i]=Ds1302_Single_Byte_Read(add);
add+=2;
}
Ds1302_Single_Byte_Write(0x8e,0x80);
}
ds1302.h
#ifndef __DS1302_H__
#define __DS1302_H__
#include< stc15f2k60s2.h >
#include< intrins.h >
/********************************************************************/
sbit SCK=P1^7;
sbit SD=P2^3;
sbit RST=P1^3;
/********************************************************************/
/*復位腳*/
#define RST_CLR RST=0 /*電平置低*/
#define RST_SET RST=1 /*電平置高*/
/*雙向數據*/
#define SDA_CLR SD=0 /*電平置低*/
#define SDA_SET SD=1 /*電平置高*/
#define SDA_R SD /*電平讀取*/
/*時鐘信號*/
#define SCK_CLR SCK=0 /*時鐘信號*/
#define SCK_SET SCK=1 /*電平置高*/
/********************************************************************/
#define ds1302_sec_addr 0x80 //秒數據地址
#define ds1302_min_addr 0x82 //分數據地址
#define ds1302_hr_addr 0x84 //時數據地址
#define ds1302_date_addr 0x86 //日數據地址
#define ds1302_month_addr 0x88 //月數據地址
#define ds1302_day_addr 0x8A //星期數據地址
#define ds1302_year_addr 0x8C //年數據地址
#define ds1302_control_addr 0x8Ee //寫保護命令字單元地址
#define ds1302_charger_addr 0x90 //涓電流充電命令字地址
#define ds1302_clkburst_addr 0xBE //日歷、時鐘突發模式命令字地址
/********************************************************************/
/********************************************************************/
/*單字節寫入一字節數據*/
extern void Write_Ds1302_Byte(unsigned char dat);
/********************************************************************/
/*單字節讀出一字節數據*/
extern unsigned char Read_Ds1302_Byte(void);
/********************************************************************/
/********************************************************************/
/*向DS1302單字節寫入一字節數據*/
extern void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat);
/********************************************************************/
/*從DS1302單字節讀出一字節數據*/
extern unsigned char Ds1302_Single_Byte_Read(unsigned char addr);
extern unsigned char time[];
extern void Ds1302_init();
extern void Ds1302_Gettime();
#endif
/********************************************************************/
// END FILE
/********************************************************************/
Text.c
#include< stc15f2k60s2.h >
#include"ds1302.h"
#define uchar unsigned char
uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
unsigned char f1,f2,f3,f4,f5,f6,f7,f8;
void delay();
void allinit();
void display12(uchar f1,uchar f2);
void display34(uchar f3,uchar f4);
void display56(uchar f5,uchar f6);
void display78(uchar f7,uchar f8);
void main()
{
allinit();
Ds1302_init();
while(1)
{
Ds1302_Gettime();
f1=time[2]/10;f2=time[2]%10;f3=10;
f4=time[1]/10;f5=time[1]%10;f6=10;
f7=time[0]/10;f8=time[0]%10;
display12(f1,f2);
display34(f3,f4);
display56(f5,f6);
display78(f7,f8);
}
}
void delay(){
unsigned int i,j;
for(i=0;i< 2;i++)
for(j=0;j< 200;j++);
}
void allinit(){
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
P2=0XC0;P0=0XFF;P2=0XFF;P0=0XFF;
}
void display12(uchar f1,uchar f2){
P2=0XC0;P0=0X01;P2=0XFF;P0=tab[f1];
delay();
P2=0XC0;P0=0X02;P2=0XFF;P0=tab[f2];
delay();
}
void display34(uchar f3,uchar f4){
P2=0XC0;P0=0X04;P2=0XFF;P0=tab[f3];
delay();
P2=0XC0;P0=0X08;P2=0XFF;P0=tab[f4];
delay();
}
void display56(uchar f5,uchar f6){
P2=0XC0;P0=0X10;P2=0XFF;P0=tab[f5];
delay();
P2=0XC0;P0=0X20;P2=0XFF;P0=tab[f6];
delay();
}
void display78(uchar f7,uchar f8){
P2=0XC0;P0=0X40;P2=0XFF;P0=tab[f7];
delay();
P2=0XC0;P0=0X80;P2=0XFF;P0=tab[f8];
delay();
}
結果與體會:
ds1302.c
此代碼和官方給出的驅動有所修改,增加了DS1302初始化函數和獲取時間的函數,還有在向DS1302單字節寫入一字節數據,修改:
Write_Ds1302_Byte((dat/10 4)|(dat%10));
/ 從DS1302單字節讀出一字節數據 /函數修改為:
dat1=temp/16;
dat2=temp%16;
temp=10*dat1+dat2;
//RST_CLR; /*停止DS1302總線*/
SD=0;
return temp;
只要注意轉換公式就可以了。
ds1302.h
要增加新定義的函數說明。
-
寄存器
+關注
關注
31文章
5363瀏覽量
121172 -
實時時鐘
+關注
關注
4文章
248瀏覽量
65967 -
DS1302
+關注
關注
8文章
449瀏覽量
50815 -
RST
+關注
關注
0文章
31瀏覽量
7425 -
時鐘信號
+關注
關注
4文章
453瀏覽量
28666
發布評論請先 登錄
相關推薦
評論