DS1302基本的读写

2019-07-14 01:58发布

  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 #include   //使用_nop_();   sbit SCL = P1^6; sbit IO  = P3^5; sbit RST = P1^7;   #define H12_24 0x80              //0b1000 0000 bit7112小时 #define AM_PM 0x20  //12小时模式下,bit51则选中了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<               }               RST = 0; //拉低停止数据传输               return readData;                                    }