| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414 |
- //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 );
- }
|