DS1302的读写

2019-07-14 02:08发布

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 控制器:stc89c5288段共阴数码管,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 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<