DS1302的读写

DS1302DALLAS公司的一个时钟芯片,能设置秒、分钟、小时、月、星期、年,且年可以设置到2100年。有时钟/日历寄存器还有31*8位的额外数据暂存寄存器(RAM),可以存储对时间的修正参数或者初始化的标志(前提是DS1302要外接备用电源),如果主机掉电后重新上电时读取RAM中的初始化标志为1的话就不对DS1302初始化了。

 

说到备用电源,可以用3.3v的锂电池或者电源掉电时间短的话(几小时或一天)则可以使用大电容(0.1F以上)供电,只是貌似电容体积太大。

 

DS1302是通过三根线控制读写数据的,RST/SCL/IO.

RST:复位线,所有数据的读写,都需要保持RST1,为0时就会终止当前的数据操作。

SCL:时钟线,提供数据操作的同步时钟。

     写入数据时,写入数据在SCL=0时可以改变而在SCL=1时要保持不变,即数据会在SCL的上升沿写入到DS1302。数据传输是低位在前,高位在后。

     读取数据时,在SCL=1变为SCL=0之后就可以读取数据(注:在写完寄存器后的一个下降沿就可以读取数据),即数据会在SCL的下降沿出现到IO数据线上。同样数据也是低位在前高位在后。

IO:数据线,要发送的八位数据,要从最低位一次移到IO数据线上。

        

时钟/日历寄存器:

 : 

     1000..R/W是寄存器地址和读写控制位,R/W1为读,为0为写。后面是寄存器里的读写数据,均是以二进制的BCD码存在的。BCD码,0-9对应0000-1001,十位对应10sec,如59对应数据为,CH1011001。下面几个寄存器数据格式亦是如此。CH=1,代表晶振停振,CH=0,代表晶振起振,时钟要工作的话都需要起振的。

 : 

小时 : 

       bit7控制是112小时制,为024小时制,bit51则选择12小时下的PM,为0则是选择24小时的20-23小时段。

 : 

 : 

星期 : 

 : 

CONTROL : 

          WP写保护位,写入时要置WP=0

还有涓流充电器寄存器,控制锂电池的充电电流。

         DS1302的突发模式是连续读写寄存器,时钟/日历的7个寄存器是必须一下读完的,而其他的寄存器没必要一下读完。

        

         读写时序,贴张图,详见DS1302的资料手册。

 

突发模式的读写没写,连续读写和普通读写就是控制指令的bit5-bit1全为1bit6控制连续读写时钟/日历或RAM

 

控制器:stc89c52

88段共阴数码管,78LS138控制位,74HC573控制数码管的各段,贴上电路图。

 

下面贴上DS1302的普通读写程序:

/*****************************************************************

*********** Name: DS1302

***********               Date: 2014/12/25

***********               Com: FairSun

***********  LOL

******************************************************************/

 

#include <reg51.h>

#include <intrins.h>  //使用_nop_();

 

sbit SCL = P1^6;

sbit IO  = P3^5;

sbit RST = P1^7;

 

#define H12_24 0x80              //0b1000 0000 bit7为1是12小时

#define AM_PM 0x20  //在12小时模式下,bit5为1则选中了PM,在24小时模式下,为1则选中了20-24小时段

#define CH 0x00  //sec设置的最高位,为0则晶振起振,为1则晶振不起振

 

const unsigned char smg_dp_yin[ 16 ] = {0xbf, 0x86, 0xdb, 0xcf, 0xe6, 0xed, 0xfd, 0x87, 0xff, 0xef,

                                                                                                                                            0xf7, 0xfc, 0xb9, 0xde, 0xfb, 0xf1};//0. 1. 2. 3......f.

                                                                                                                                            //共阴极,显示小数点

                                                                                                                                            //不显示小数点:  smg_dp_yin[x] | 0x80

                                                                                                                              //共阳极显示小数点: ~smg_dp_yin[x]

                                                                                                                  //共阳极不显示小数点: ~(smg_dp_yin[x] | 0x80)

 

const unsigned char smg_8_pos[ 8 ] = { 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; //对应P20,P21,P22,高位都为1,则与的时候P2的其他位不变

const unsigned char smg_sum = 8;  //8位数码管

 

unsigned char smg_8_data[ 8 ] = { 0 };

 

struct HMS{

              unsigned char hour;

              unsigned char min;

              unsigned char sec;

};

 

struct MD{

              unsigned char month;

              unsigned char date;  //一月的几日

};

 

struct YD{

              unsigned char year;

              unsigned char day;  //星期几

};

 

struct ALLDATE{

              struct YD yd;

              struct MD md;

              struct HMS hms;        

};

 

void per_init( void );

void delay_xms( unsigned int );

//void Timer0_init( void );

//void Timer0_server( void );

void ds1302_delay( void );

void Display_Time( struct ALLDATE allDate );

unsigned char DecToBCD(unsigned char mData);

unsigned char BCDToDec(unsigned char mData);

struct ALLDATE convertToSetTime(struct ALLDATE allDate);

struct ALLDATE convertToDisplayTime(struct ALLDATE allDate);

void ds1302_setTime(struct ALLDATE allDate);

struct ALLDATE ds1302_readTime( void );

void ds1302_writeByte(unsigned char mCommand, unsigned char mData);

unsigned char ds1302_readByte(unsigned char mCommand);

 

void main(void)

{

              struct ALLDATE allDate = { {99, 4}, {12, 14}, {23, 59, 55} };  //设置时间:2099-12-14 星期4 23:59:55

              per_init();

              ds1302_setTime(allDate);

              while( 1 )

              {

                            allDate = ds1302_readTime();

                            Display_Time(allDate);

              }

}

 

/************************************************************************

**函数名:void delay_xms( unsigned int x )

**  功能:延时xms

**  参数: 无

*************************************************************************/

void delay_xms( unsigned int x )

{

              unsigned char j = 0;

              while( x-- )

              {

                            while( (j++) < 100 );

                            j = 0;

              }

}

 

/************************************************************************

**函数名:void Per_init( void )

**  功能:各个外设初始配置

**  参数: 无

*************************************************************************/

void per_init( void )

{

              P0 = 0xff;

              P1 = 0xff;

              P2 = 0xff;

              P3 = 0xff;         

}

 

/************************************************************************

**函数名:void Timer0_init( void )

**  功能:定时器0初始配置

**  参数: 无

*************************************************************************/

/*void Timer0_init( void )

{

                           

              TMOD |= 0x01; //设置定时器0的模式为16位

              TH0 = ( 65536-46000 ) / 256;

              TL0 = (65536-46000) % 256;

              if( EA != 1 )

                            EA = 1;

              ET0 = 1;  //打开定时器0的中断

              TR0 = 0;  //定时器0暂停

}

 */

/************************************************************************

**函数名:定时器0的中断服务函数

**  功能:装初值

**  参数: 无

*************************************************************************/

/*void Timer0_server( void ) interrupt 1

{

                            TH0 = (65536-46000) / 256;

                            TL0 = (65536-46000) % 256;

}  */

 

/************************************************************************

**函数名:void Display_Time(void)

**  功能:显示时间

**  参数: 无

*************************************************************************/

void Display_Time(struct ALLDATE allDate)  //显示分钟

{

              unsigned char pos;

              unsigned char *pallDate = (unsigned char *)&allDate;

              for(pos = 0; pos <= 7; pos+=2)

              {

                            smg_8_data[pos] = *(pallDate+(pos>>1)) / 10 % 10;

                            smg_8_data[pos+1] = *(pallDate+(pos>>1))%10;

              }

              /*smg_8_data[0] = allDate.yd.year / 10 % 10;

              smg_8_data[1] = allDate.yd.year%10;

              smg_8_data[2] = allDate.hms.hour / 10 % 10;

              smg_8_data[3] = allDate.hms.hour%10;

              smg_8_data[4] = allDate.hms.min / 10 % 10;

              smg_8_data[5] = allDate.hms.min%10;

              smg_8_data[6] = allDate.hms.sec / 10 % 10;

              smg_8_data[7] = allDate.hms.sec%10;          */

              for( pos = 0; pos < smg_sum; pos++ )

              {            

                            P2 &= 0xf8;

                            P2 |= smg_8_pos[pos];

                            P0 = smg_dp_yin[smg_8_data[pos]]&0x7f;

                            delay_xms(1);                           

              }            

}

 

void ds1302_delay( void )

{

              int i;

              for(i = 0; i < 1; i++)

              {

                            _nop_();

              }

}

 

/************************************************************************

**函数名:unsigned char DecToBCD(unsigned char mData)

**  功能:10进制转为BCD码

**  参数: unsigned char mData

*************************************************************************/

unsigned char DecToBCD(unsigned char mData)

{

              unsigned char BCD = 0;

              while(mData >= 10)

              {

                            mData -= 10;

                            BCD ++;            

              }

              BCD <<= 4;

              BCD |= mData;

              return BCD;

}

 

/************************************************************************

**函数名:unsigned char BCDToDec(unsigned char mData)

**  功能:BCD码转为10进制

**  参数: unsigned char mData

*************************************************************************/

unsigned char BCDToDec(unsigned char mData)

{

              unsigned char Dec = 0;

              Dec = mData & 0x0f;  //取得最低位

              mData = mData & 0x70;  //剔除最高位和最低四位

              Dec += mData>>1; //先左移1代表*2

              Dec += mData>>3; //再左移3代表*8,所以总的相当于乘以10

              return Dec;

}

 

/*

struct ALLDATE convertToSetTime(struct ALLDATE allDate)

{

              struct ALLDATE mAllDate;

              mAllDate.yd.year = ((allDate.yd.year/10)<<4) + (allDate.yd.year%10);

              mAllDate.yd.day = allDate.yd.day;

              mAllDate.md.month = ((allDate.md.month/10)<<4) + (allDate.md.month%10);

              mAllDate.md.date = ((allDate.md.date/10)<<4)  + (allDate.md.date%10);

              mAllDate.hms.hour = H12_24 + AM_PM + ((allDate.hms.hour/10)<<4) + (allDate.hms.hour%10);

              mAllDate.hms.min = ((allDate.hms.min/10)<<4) + (allDate.hms.min%10);

              mAllDate.hms.sec = CH + ((allDate.hms.sec/10)<<4) + (allDate.hms.sec%10);

              return mAllDate;

}

 

struct ALLDATE convertToDisplayTime(struct ALLDATE allDate)

{

              struct ALLDATE mAllDate;

              mAllDate.yd.year = ((allDate.yd.year/10)>>4)*10 + (allDate.yd.year%10);

              mAllDate.yd.day = allDate.yd.day;

              mAllDate.md.month = ((allDate.md.month/10)<<4) + (allDate.md.month%10);

              mAllDate.md.date = ((allDate.md.date/10)<<4)  + (allDate.md.date%10);

              mAllDate.hms.hour = H12_24 + AM_PM + ((allDate.hms.hour/10)<<4) + (allDate.hms.hour%10);

              mAllDate.hms.min = ((allDate.hms.min/10)<<4) + (allDate.hms.min%10);

              mAllDate.hms.sec = CH + ((allDate.hms.sec/10)<<4) + (allDate.hms.sec%10);

              return mAllDate;      

} */

 

/************************************************************************

**函数名:struct ALLDATE convertToSetTime(struct ALLDATE allDate)

**  功能:将设置的时间转为BCD码

**  参数: struct ALLDATE allDate

*************************************************************************/

struct ALLDATE convertToSetTime(struct ALLDATE allDate)

{

              unsigned char loop;

              struct ALLDATE mAllDate;

              unsigned char *pallDate = (unsigned char *)&allDate;

              unsigned char *pmAllDate = (unsigned char *)&mAllDate;

              for(loop = 0; loop <= 7; loop++)

              {

                            *(pmAllDate+loop) = DecToBCD(*(pallDate+loop));            

              }

              /*mAllDate.yd.year = DecToBCD(allDate.yd.year);

              mAllDate.yd.day = DecToBCD(allDate.yd.day);

              mAllDate.md.month = DecToBCD(allDate.md.month);      //((allDate.md.month/10)<<4) + (allDate.md.month%10);

              mAllDate.md.date = DecToBCD(allDate.md.date);              //((allDate.md.date/10)<<4)  + (allDate.md.date%10);

              mAllDate.hms.hour = DecToBCD(allDate.hms.hour);//H12_24 + AM_PM +   H12_24 + AM_PM + ((allDate.hms.hour/10)<<4) + (allDate.hms.hour%10);

              mAllDate.hms.min = DecToBCD(allDate.hms.min);             //((allDate.hms.min/10)<<4) + (allDate.hms.min%10);

              mAllDate.hms.sec = CH + DecToBCD(allDate.hms.sec);//CH + ((allDate.hms.sec/10)<<4) + (allDate.hms.sec%10); */

              return mAllDate;

}

 

/************************************************************************

**函数名:struct ALLDATE convertToDisplayTime(struct ALLDATE allDate)

**  功能:将读取的BCD码转为10进制要显示的数据

**  参数: struct ALLDATE allDate

*************************************************************************/

struct ALLDATE convertToDisplayTime(struct ALLDATE allDate)

{

              unsigned char loop;

              struct ALLDATE mAllDate;

              unsigned char *pallDate = (unsigned char *)&allDate;

              unsigned char *pmAllDate = (unsigned char *)&mAllDate;

              for(loop = 0; loop <= 7; loop ++)

              {

                            *(pmAllDate+loop) = BCDToDec(*(pallDate+loop));

              }

              /*mAllDate.yd.year = (((allDate.yd.year&0x80)>>4)*10) + BCDToDec(allDate.yd.year);           //(((allDate.yd.year&0x80)>>4)*10) +

              mAllDate.yd.day = BCDToDec(allDate.yd.day);

              mAllDate.md.month = BCDToDec(allDate.md.month);      //((allDate.md.month/10)<<4) + (allDate.md.month%10);

              mAllDate.md.date = BCDToDec(allDate.md.date);              //((allDate.md.date/10)<<4)  + (allDate.md.date%10);

              mAllDate.hms.hour = BCDToDec(allDate.hms.hour);//0x1f&   H12_24 + AM_PM + ((allDate.hms.hour/10)<<4) + (allDate.hms.hour%10);

              mAllDate.hms.min = BCDToDec(allDate.hms.min);             //((allDate.hms.min/10)<<4) + (allDate.hms.min%10);

              mAllDate.hms.sec = BCDToDec(allDate.hms.sec);//CH + ((allDate.hms.sec/10)<<4) + (allDate.hms.sec%10); */

              return mAllDate;       

}

 

/************************************************************************

**函数名:void ds1302_setTime(struct ALLDATE allDate)

**  功能:把时间写入到DS1302

**  参数: struct ALLDATE allDate

*************************************************************************/

void ds1302_setTime(struct ALLDATE allDate)

{

              unsigned char loop;

              unsigned char *pallDate = (unsigned char *)&allDate;

              allDate = convertToSetTime(allDate);

              ds1302_writeByte(0x8e, 0x00);  //control为的最高位wp

              for(loop = 0; loop <= 6; loop++)

              {

                            ds1302_writeByte(0x8c-(loop<<1), *(pallDate+loop));  //sec                  

              }

              /*ds1302_writeByte(0x8e, 0x00);  //control为的最高位wp

              ds1302_writeByte(0x8c, allDate.yd.year);  //year

              ds1302_writeByte(0x8a, allDate.yd.day);  //day

              ds1302_writeByte(0x88, allDate.md.month);  //month

              ds1302_writeByte(0x86, allDate.md.date);  //date

              ds1302_writeByte(0x84, allDate.hms.hour);  //hour

              ds1302_writeByte(0x82, allDate.hms.min);  //min

              ds1302_writeByte(0x80, allDate.hms.sec);  //sec            */

}

 

/************************************************************************

**函数名:struct ALLDATE ds1302_readTime( void )

**  功能:从DS1302读取时间信息

**  参数: struct ALLDATE allDate

*************************************************************************/

struct ALLDATE ds1302_readTime( void )

{

              unsigned char loop;

              struct ALLDATE allDate;

              unsigned char *pallDate = (unsigned char *)&allDate;

              for(loop = 0; loop <= 6; loop++)

              {

                            *(pallDate+loop) = ds1302_readByte(0x8d-(loop<<1));                

              }

              /*allDate.yd.year =  ds1302_readByte(0x8d);  //year

              allDate.yd.day =   ds1302_readByte(0x8b);  //day

              allDate.md.month = ds1302_readByte(0x89);  //month

              allDate.md.date =  ds1302_readByte(0x87);  //date

              allDate.hms.hour = ds1302_readByte(0x85);  //hour

              allDate.hms.min =  ds1302_readByte(0x83);  //min

              allDate.hms.sec =  ds1302_readByte(0x81);  //sec  */

              allDate = convertToDisplayTime(allDate);

              return allDate;            

}

 

/************************************************************************

**函数名:void ds1302_writeByte(unsigned char mCommand, unsigned char mData)

**  功能:往DS1302写入一个字节

**  参数: unsigned char mCommand, unsigned char mData

*************************************************************************/

void ds1302_writeByte(unsigned char mCommand, unsigned char mData)

{

              int loop;

              RST = 0;

              SCL = 0;

              ds1302_delay();

              RST = 1;

              ds1302_delay();

              for(loop = 0; loop < 8; loop++)

              {

                            IO = (mCommand>>loop)&0x01;

                            ds1302_delay();

                            SCL = 1;

                            ds1302_delay();

                            SCL = 0;

                            ds1302_delay();                       

              }

              for(loop = 0; loop < 8; loop++)

              {

                            IO = (mData>>loop)&0x01;

                            ds1302_delay();

                            SCL = 1;

                            ds1302_delay();

                            SCL = 0;

                            ds1302_delay();                       

              }

              RST = 0; //拉低停止数据传输                                    

}

 

/************************************************************************

**函数名:unsigned char ds1302_readByte(unsigned char mCommand)

**  功能:从DS1302读取一个字节

**  参数: unsigned char mCommand

*************************************************************************/

unsigned char ds1302_readByte(unsigned char mCommand)

{

              unsigned char loop = 0;

              unsigned char readData = 0;

              unsigned char temp = 0;

              RST = 1; //必须置高

              for(loop = 0; loop < 8; loop++)

              {

                            IO = (mCommand>>loop)&0x01;

                            SCL = 1;

                            ds1302_delay();

                            SCL = 0;                          

              }

              for(loop = 0; loop < 8; loop++)

              {

                           

                            temp = IO;

                            SCL = 1;

                            ds1302_delay();         

                            SCL = 0;

                            readData += (temp<<loop); 

              }

              RST = 0; //拉低停止数据传输

              return readData;                                   

}

猜你喜欢

转载自blog.csdn.net/weibo1230123/article/details/80289738