//ds1302.c: /************ DS1302程序 ************ * 版本.........: 1.0 * 作者.........: 陈利栋 * 文件名.......: ds1302.c * 创建时间.....: 2010.11.11 * 最后修改.....: 2010.11.11 ************************************/ #include "ds1302.h" #include "ds1302_config.h" volatile unsigned char DS1302_Update = 0; DS1302_DateTime_t DS1302_DateTime; // 发送一个字节,不操作CE static void DS1302_TxByte ( unsigned char byte ) { unsigned char i = 0; DS1302_IO_OUT; for ( i = 0; i < 8; i++ ) { DS1302_SCLK_0; DS1302_DELAY_T_CL; if ( byte & 0x01 ) { DS1302_IO_1; } else { DS1302_IO_0; } DS1302_DELAY_T_DC; DS1302_SCLK_1; DS1302_DELAY_T_CH; byte >>= 1; } } // 接收一个字节,不操作CE static unsigned char DS1302_RxByte ( void ) { unsigned char i = 0; unsigned char byte = 0; DS1302_IO_IN; DS1302_IO_1; for ( i = 0; i < 8; i++ ) { DS1302_SCLK_0; DS1302_DELAY_T_CDD; byte >>= 1; if ( DS1302_IO_VALUE ) { byte |= 0x80; } DS1302_SCLK_1; DS1302_DELAY_T_CH; } return byte; } static void DS1302_WriteByte ( unsigned char address, unsigned char _data ) { DS1302_SCLK_0; DS1302_CE_1; DS1302_DELAY_T_CC; DS1302_TxByte ( address ); DS1302_TxByte ( _data ); DS1302_SCLK_0; DS1302_DELAY_T_CCH; DS1302_CE_0; DS1302_DELAY_T_CWH; } static unsigned char DS1302_ReadByte ( unsigned char address ) { unsigned char _data = 0; DS1302_SCLK_0; DS1302_CE_1; DS1302_DELAY_T_CC; DS1302_TxByte ( address | 0x01 ); _data = DS1302_RxByte(); DS1302_SCLK_0; DS1302_DELAY_T_CCH; DS1302_CE_0; DS1302_DELAY_T_CWH; return _data; } #if DS1302_AUTO_TO_DEC == 1 static unsigned char DecToBcd ( unsigned char d ) { return ( ( ( ( d ) / 10 ) << 4 ) + ( ( d ) % 10 ) ); } static unsigned char BcdToDec ( unsigned char b ) { return ( ( ( ( b ) >> 4 ) * 10 ) + ( ( b ) & 0x0f ) ); } #endif /* DS1302_AUTO_TO_DEC == 1 */ void DS1302_SetDateTime ( void ) { unsigned char temp = 0; DS1302_WriteByte ( DS1302_WRITE_PROTECT_ADDR, 0x00 ); // 关闭写保护 DS1302_WriteByte ( DS1302_YEAR_ADDR, DEC_TO_BCD ( DS1302_DateTime.Year ) ); DS1302_WriteByte ( DS1302_MONTH_ADDR, DEC_TO_BCD ( DS1302_DateTime.Month ) ); DS1302_WriteByte ( DS1302_DATE_ADDR, DEC_TO_BCD ( DS1302_DateTime.Date ) ); DS1302_WriteByte ( DS1302_MINUTE_ADDR, DEC_TO_BCD ( DS1302_DateTime.Minute ) ); DS1302_WriteByte ( DS1302_SECOND_ADDR, DEC_TO_BCD ( DS1302_DateTime.Second ) ); DS1302_WriteByte ( DS1302_DAY_ADDR, DEC_TO_BCD ( GetDayFromDate ( DS1302_DateTime.Year, DS1302_DateTime.Month, DS1302_DateTime.Date ) ) ); temp = DEC_TO_BCD ( DS1302_DateTime.Hour ); if ( DS1302_DateTime.HourMode == _12_hours ) { temp |= 0x80; temp |= ( DS1302_DateTime.AM_PM == pm ? 0x20 : 0 ); } DS1302_WriteByte ( DS1302_HOUR_ADDR, temp ); DS1302_WriteByte ( DS1302_WRITE_PROTECT_ADDR, 0x80 ); // 写入完毕后设置写保护 } void DS1302_GetDateTime ( void ) { unsigned char temp = 0; DS1302_Update = 0; DS1302_DateTime.Year = BCD_TO_DEC ( DS1302_ReadByte ( DS1302_YEAR_ADDR ) ); DS1302_DateTime.Month = BCD_TO_DEC ( DS1302_ReadByte ( DS1302_MONTH_ADDR ) ); DS1302_DateTime.Date = BCD_TO_DEC ( DS1302_ReadByte ( DS1302_DATE_ADDR ) ); DS1302_DateTime.Minute = BCD_TO_DEC ( DS1302_ReadByte ( DS1302_MINUTE_ADDR ) ); DS1302_DateTime.Second = BCD_TO_DEC ( DS1302_ReadByte ( DS1302_SECOND_ADDR ) ); DS1302_DateTime.Day = BCD_TO_DEC ( DS1302_ReadByte ( DS1302_DAY_ADDR ) ); temp = DS1302_ReadByte ( DS1302_HOUR_ADDR ); if ( temp & 0x80 ) { DS1302_DateTime.HourMode = _12_hours; DS1302_DateTime.AM_PM = ( ( temp & 0x20 ) ? pm : am ); temp &= 0x1f; } DS1302_DateTime.Hour = BCD_TO_DEC ( temp ); } void DS1302_Scan ( void ) { static unsigned second_last = 0; DS1302_DateTime.Second = BCD_TO_DEC ( DS1302_ReadByte ( DS1302_SECOND_ADDR ) ); if ( second_last != DS1302_DateTime.Second ) { second_last = DS1302_DateTime.Second; DS1302_Update = 1; } } void DS1302_Init ( void ) { #if DS1302_def // 端口初始化 DS1302_CE_0; DS1302_CE_OUT; DS1302_SCLK_0; DS1302_SCLK_OUT; DS1302_WriteByte ( DS1302_WRITE_PROTECT_ADDR, 0x00 ); // 关闭写保护 DS1302_WriteByte ( DS1302_TRICKLE_CHARGE_ADDR, 0xa7 ); // 使能涓流充电 1 Diode, 8kΩ if ( DS1302_ReadByte ( DS1302_SECOND_ADDR ) & 0x80 ) // 振荡器未启动 DS1302_WriteByte ( DS1302_SECOND_ADDR, 0x00 ); // 启动振荡器 DS1302_WriteByte ( DS1302_WRITE_PROTECT_ADDR, 0x80 ); // 打开写保护 #endif } void DS1302_Key_Handler ( void ) { if ( Keys[14].Res == LONG_KEY_FLAG ) { Keys[14].Res = NO_KEY_FLAG; DS1302_DateTime.Year = 14; DS1302_DateTime.Month = 10; DS1302_DateTime.Date = 5; DS1302_DateTime.Hour = 22; DS1302_DateTime.Minute = 35; DS1302_DateTime.Second = 0; DS1302_DateTime.Day = 7; DS1302_DateTime.HourMode = _24_hours; DS1302_DateTime.AM_PM = pm; #if DS1302_def DS1302_SetDateTime(); #endif } } // 计算2000~2099年任一天星期几 // year : 00-99 // month : 01-12 // day : 01-31 // 返回 1 -> 7 : 星期一 -> 星期天 unsigned char GetDayFromDate ( unsigned char year, unsigned char month, unsigned char date ) { if ( month == 1 || month == 2 ) { month += 12; if ( year > 0 ) year--; else year = 4; } return ( 1 + ( ( date + 2 * month + 3 * ( month + 1 ) / 5 + year + year / 4 ) % 7 ) ); } ///////////////////// //平年的月份日期表,月份缩写表 const u8 Days_Table[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const u8 Month_Table[12][3] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; const u8* Week_Table[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; //月修正数据表 u8 const _Week[12] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5}; //判断是否是闰年函数 // //判断方法: // 普通年能整除4且不能整除100的为闰年。(如2004年就是闰年,1900年不是闰年) // 世纪年能整除400的是闰年。(如2000年是闰年,1900年不是闰年) // //返回: 1,是闰年 0,不是闰年 u8 Is_LeapYear ( u16 year ) { if ( ( ( year % 4 == 0 ) && ( year % 100 != 0 ) ) || ( year % 400 == 0 ) ) return 1; else return 0; } //将时间转化为到1970年1月1日的总秒数 //Bugs:此函数秒数会多20左右,所以函数返回值做了校正,校正后没有问题 //待优化 u32 Date_TO_Sec ( u16 year, u8 month, u8 date, u8 hour, u8 minute, u8 second ) { u16 t = 0; u32 sec = 0; year += 2000; if ( ( year >= 1970 ) && ( year <= 2106 ) ) //判断是否为合法年份,RTC的时间是从1970开始,只能由32位表示秒数,最大只能到2106年左右 { for ( t = 1970 ; t < year; t++ ) //所有年份秒数累加 { if ( Is_LeapYear ( t ) ) //判断是否为闰年 { sec += 366 * 24 * 60 * 60; } else { sec += 365 * 24 * 60 * 60; } } for ( t = 0; t < month - 1; t++ ) //月份秒数累加 { sec += ( u32 ) Days_Table[t] * 24 * 60 * 60; if ( Is_LeapYear ( year ) && ( t == 1 ) ) //闰年加一天的秒钟数 { sec += 24 * 60 * 60; } } sec += ( u32 ) ( date - 1 ) * 24 * 60 * 60; //本月日期的秒数累加 sec += ( u32 ) ( hour ) * 60 * 60; sec += ( u32 ) ( minute ) * 60; sec += second; } return sec;//-20; //校正20秒,原因不详 } //获取RTC时间 void Sec_TO_Date ( u32 secs ) { u32 days = 0, temp = 0, years = 1970, months = 0; #if 0 secs = RTC->CNTH; //读取RTC的当前时间值(距1970年的总秒数) secs <<= 16; secs += RTC->CNTL; #else #endif //printf("\nRtc_Get Sec = %x\n",secs); days = secs / ( 24 * 60 * 60 ); if ( days > 0 ) //超过一天 { temp = days; while ( temp >= 365 ) { if ( Is_LeapYear ( years ) ) //是闰年 { if ( temp >= 366 ) { temp -= 366; //闰年的天数 } else { break; } } else { temp -= 365; } years++; } DS1302_DateTime.Year = years - 2000; //得到年份 while ( days >= 28 ) { if ( Is_LeapYear ( years ) && ( months == 1 ) ) //判断是否为闰年的第二月 { if ( temp >= 29 ) temp -= 29; else break; } else { if ( temp >= Days_Table[months] ) temp -= Days_Table[months]; else break; } months++; } DS1302_DateTime.Month = months + 1; //得到月数 DS1302_DateTime.Date = temp + 1; //得到日期 } temp = secs % ( 24 * 60 * 60 ); //得到剩余秒数 DS1302_DateTime.Hour = temp / ( 60 * 60 ); //得到小时 DS1302_DateTime.Minute = ( temp % ( 60 * 60 ) ) / 60; DS1302_DateTime.Second = ( temp % ( 60 * 60 ) ) % 60; DS1302_DateTime.Day = GetDayFromDate ( DS1302_DateTime.Year, DS1302_DateTime.Month, DS1302_DateTime.Date ); DS1302_DateTime.HourMode = _24_hours; DS1302_DateTime.AM_PM = pm; } //计算今天是一年中的第多少天 int sum_Yday ( int a, int b, int c ) { int i; char h1[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; char h2[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; for ( i = 1; i < b; i++ ) { if ( a % 4 == 0 && a % 100 != 0 || a % 400 == 0 ) c = h1[i] + c; else c = h2[i] + c; } return ( c ); }