[Cortex-M0技术交流] 分享我的RTC应用中的秒和时间的转换函数

[复制链接]
3604|2
 楼主| gdmgb520 发表于 2012-6-18 18:33 | 显示全部楼层 |阅读模式
主要是秒和年月日时分秒之间的相互转换。开始在网上找了写资料,包括野火的和正点原子的例程。都有一些小问题或者不是十分满足我的要求。最后修改的结果如下。已经做了些测试,也希望大家不要拿来直接用,确认没有问题再用。


time.c文件:
  1. #define FEBRUARY                2
  2. #define        STARTOFTIME                1970
  3. #define SECDAY                        86400L
  4. #define SECYR                        (SECDAY * 365)
  5. #define        leapyear(year)                ((year) % 4 == 0)
  6. #define        days_in_year(a)         (leapyear(a) ? 366 : 365)
  7. #define        days_in_month(a)         (month_days[(a) - 1])


  8. extern _strTime g_SysTime;

  9. static const u8 MonthDay[2][12] = {
  10. {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},   //非闰年
  11. {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}    //闰年
  12. };

  13. /*
  14. * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
  15. */
  16. /*计算公历*/   //gb 计算星期 2012-04-27 星期五 13:56:10
  17. static void GregorianDay(_strTime* tm)
  18. {
  19.         int leapsToDate;
  20.         int lastYear;
  21.         int day;
  22.         int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };

  23.         lastYear=tm->tm_year-1;

  24.         /*计算从公元元年到计数的前一年之中一共经历了多少个闰年*/
  25.         leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;      

  26.      /*如若计数的这一年为闰年,且计数的月份在2月之后,则日数加1,否则不加1*/
  27.         if((tm->tm_year%4==0) &&
  28.            ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) &&
  29.            (tm->tm_mon>2)) {
  30.                 /*
  31.                  * We are past Feb. 29 in a leap year
  32.                  */
  33.                 day=1;
  34.         } else {
  35.                 day=0;
  36.         }

  37.         day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_day; /*计算从公元元年元旦到计数日期一共有多少天*/

  38.         tm->tm_wday=day%7;
  39. }

  40. /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
  41. * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
  42. * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
  43. *
  44. * [For the **n calendar (which was used in Russia before 1917,
  45. * Britain & colonies before 1752, anywhere else before 1582,
  46. * and is still in use by some communities) leave out the
  47. * -year/100+year/400 terms, and add 10.]
  48. *
  49. * This algorithm was first published by Gauss (I think).
  50. *
  51. * WARNING: this function will overflow on 2106-02-07 06:28:16 on
  52. * machines were long is 32-bit! (However, as time_t is signed, we
  53. * will already get problems at other places on 2038-01-19 03:14:08)
  54. */
  55. //        u32 mktimev(_strTime *tm)
  56. uint32_t ap_time_date2sec(_strTime *Time)
  57. {
  58. //          char Temp = 0;
  59.   _strTime tmp = {0,0,0,0,0,0,0};
  60. //          u32 lTime = 0;

  61. //   tmp = g_SysTime;
  62.   tmp.tm_sec = Time->tm_sec;
  63.   tmp.tm_min = Time->tm_min;
  64.   tmp.tm_hour = Time->tm_hour;
  65.   tmp.tm_day = Time->tm_day;
  66.   tmp.tm_mon = Time->tm_mon;
  67.   tmp.tm_year = Time->tm_year;

  68. //                if (0 >= (int) (tm.tm_mon -= 2)) {        /* 1..12 -> 11,12,1..10 */
  69.   if (0 >= (s8) (tmp.tm_mon -= 2)) {  /* 1..12 -> 11,12,1..10 */
  70.                 tmp.tm_mon += 12;                /* Puts Feb last since it has leap day */
  71.                 tmp.tm_year -= 1;
  72.         }

  73.         return (((
  74.                 (u32) (tmp.tm_year/4 - tmp.tm_year/100 + tmp.tm_year/400 + 367*tmp.tm_mon/12 + tmp.tm_day) +
  75.                         tmp.tm_year*365 - 719499
  76.             )*24 + tmp.tm_hour /* now have hours */
  77.           )*60 + tmp.tm_min /* now have minutes */
  78.         )*60 + tmp.tm_sec; /* finally seconds */
  79. }

  80. /******************************************************************************
  81. *Function        : ap_sec2date
  82. *CreatDate: 2012-04-27 星期五 14:11:31
  83. *Author                :
  84. *
  85. *Descrip        : 将秒转换为日期
  86. *Input                : tim - 秒,tm - 日期结构体指针,用于保存转换结果
  87. *Output                :
  88. *
  89. *Note                :
  90. ******************************************************************************/
  91. void ap_time_sec2date(u32 tim, _strTime * tm)
  92. {
  93.         register u32    i;
  94.         register long   hms, day;

  95.         day = tim / SECDAY;
  96.         hms = tim % SECDAY;

  97.         /* Hours, minutes, seconds are easy */
  98.         tm->tm_hour = hms / 3600;
  99.         tm->tm_min = (hms % 3600) / 60;
  100.         tm->tm_sec = (hms % 3600) % 60;

  101.         /* Number of years in days */ /*算出当前年份,起始的计数年份为1970年*/
  102.         for (i = STARTOFTIME; day >= days_in_year(i); i++) {
  103.                 day -= days_in_year(i);
  104.         }
  105.         tm->tm_year = i;

  106.         /* Number of months in days left */ /*计算当前的月份*/
  107. //                if (leapyear(tm->tm_year)) {
  108. //                        days_in_month(FEBRUARY) = 29;
  109. //                }
  110.         for(i = 1; day >= MonthDay[leapyear(tm->tm_year)][i-1]; i++)
  111.         {
  112.                 day -= MonthDay[leapyear(tm->tm_year)][i-1];
  113.         }
  114. //                days_in_month(FEBRUARY) = 28;
  115.         tm->tm_mon = i;

  116.         /* Days are what is left over (+1) from all that. *//*计算当前日期*/
  117.         tm->tm_day = day + 1;

  118.         /* Determine the day of week*/
  119.         GregorianDay(tm);
  120. }

  121. /*===================================================================
  122. 名    称:Is_Leap_Year
  123. 功    能:
  124. 入口参数:uint16 year
  125. 出口参数:uint8 TRUE or FALSE
  126. 作    者:
  127.   WebSite:www.elecbench.com
  128. 创建日期:2011-3-30 17:14:05
  129. 修改日期:
  130. 说    明:
  131. ===================================================================*/
  132. BOOL Is_Leap_Year(u16 nyear)
  133. {

  134.     if ((nyear % 4 == 0 && nyear % 100 != 0 )|| (nyear % 400 == 0))
  135.         return TRUE;
  136.     return FALSE;
  137. }

  138. /*===================================================================
  139. 名    称:Caculate_Weekday
  140. 功    能:根据年月日获得星期
  141. 入口参数:系统日期结构体变量地址 &_system_date
  142. 出口参数:
  143. 作    者:
  144.   WebSite:www.elecbench.com
  145. 创建日期:2011-3-30 17:14:01
  146. 修改日期:
  147. 说    明:
  148. ===================================================================*/
  149. //        void Caculate_Weekday(DATE *p_date)
  150. //        {
  151. //            uint16 y;
  152. //            uint8 m,d,c;
  153. //                uint16 w;
  154. //            y = p_date->year;
  155. //            m = p_date->month;
  156. //            d = p_date->day;
  157. //                if(m==1) {m=13;y -= 1;}
  158. //                if(m==2) {m=14;y -= 1;}
  159. //                c = y / 100;
  160. //                y %= 100;
  161. //       
  162. //                w = (y + y/4 + c/4 -2*c + (26*(m+1)/10) + d - 1)%7;
  163. //                p_date->_weekday = (WEEKDAY)w;
  164. //        }

  165. /*===================================================================
  166. 名    称:Time_Add_Secd
  167. 功    能:系统日期时间刷新
  168. 入口参数:日期变量和时间变量地址
  169. 出口参数:
  170. 作    者:
  171.   WebSite:www.elecbench.com
  172. 创建日期:2011-3-30 17:13:55
  173. 修改日期:
  174. 说    明:
  175. ===================================================================*/
  176. void ap_time_add_sec(_strTime* pTime)
  177. {
  178.   if (++(*pTime).tm_sec > 59)
  179.   {
  180.     (*pTime).tm_sec = 0;        //此时(*p_time).secd已经等于60,可能导致显示60,可以考虑在这里关中断
  181.     RefreshTime标志寄存器 = TRUE;  //置刷新待机界面标志
  182.     if (++(*pTime).tm_min > 59)
  183.     {
  184.       (*pTime).tm_min = 0;
  185.       if (++(*pTime).tm_hour > 23)
  186.       {
  187.         (*pTime).tm_hour = 0;
  188.         if (++pTime->tm_day > MonthDay[leapyear(pTime->tm_year)][pTime->tm_mon-1])
  189.         {
  190.           pTime->tm_day = 1;
  191.           if (++pTime->tm_mon > 12)
  192.           {
  193.             pTime->tm_mon = 1;
  194.             pTime->tm_year++;
  195.           }
  196.         }
  197. //                                        if (++pTime->_weekday > sat)
  198. //                                        {
  199. //                                                pTime->_weekday = sun;
  200. //                                        }
  201.       }
  202.     }
  203.   }
  204. }


tiem.h文件:
  1. #include "config.h"
  2. #include "include.h"

  3. typedef struct
  4. {
  5.         u16 tm_year;    //年
  6.         u8  tm_mon;     //月
  7.         u8  tm_day;   //日
  8.         u8  tm_hour;     //小时
  9.         u8  tm_min;      //分钟
  10.         u8  tm_sec;      //秒
  11.         u8  tm_wday;   //星期
  12. }_strTime;
  13.    
  14. u32 ap_time_date2sec(_strTime *tm);
  15. void ap_time_sec2date(u32 tim, _strTime * tm);
  16. void ap_time_add_sec(_strTime* pTime);
xyz549040622 发表于 2012-6-19 08:17 | 显示全部楼层
顶,有空测试下
 楼主| gdmgb520 发表于 2012-6-19 09:27 | 显示全部楼层
呵呵,要找这么个可靠的程序真的是不容易。
哇哦在网上找了好几个版本,首先要自己看明白,觉得没有逻辑问题,然后还要实际测试能通过。
发现一些错误,我已经做了修改。大家有空也试试。
这个可以收藏,呵呵,以备不时之需;P
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:了解新东西才知道自己的不足。 www.elecbench.com

67

主题

452

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部