TIMERを使用してRTCクロックをシミュレートする

TIMERを使用してRTCクロックをシミュレートする

RTCクロックを実現するために、STM32F103のRTC.cの2つの関数を借用します。
利点:強力な移植性と正確なタイミング。
短所:電源をオンにするたびに時間を調整する必要があります。
該当する場合:外部RTC水晶発振器なし、時間校正。
使用手順:
1:最初にタイムベースを決定します。つまり、計算の開始点は何時ですか。2020年1月1日の0:00:00:00から開始します。関連する定義は次のとおりです。

#define     START_YEAR      2000//default 2000, Jan.1, 00:00:00

#define     SEC_IN_DAY      86400//1 day includes 86400 seconds


typedef     struct
{
    
           /* date and time components */
    int16_t     sec;    //senconds after the minute, 0 to 59
    int16_t     min;    //minutes after the hour, 0 to 59
    int16_t     hour;   //hours since midnight, 0 to 23
    int16_t     mday;   //day of the month, 1 to 31
    int16_t     month;  //months of the year, 1 to 12
    int16_t     year;   //years, START_YEAR to START_YEAR+135
    int16_t     wday;   //days since Sunday, 0 to 6
    int16_t     yday;   //days of the year, 1 to 366
}Calendar_TypeDef;

2:MyMakeTime()は、時間校正によって取得された時間(年、月、日、時、分、秒)をSTART_YEARからの秒数として計算します。MyMakeTime関数は、ホストコンピューターによって発行された時刻校正時間を取得するときに一度だけ呼び出されます。
MyMakeTime関数によって返された秒数をTIMERタイマー割り込みに入れ、1秒に1回累積します。RTCクロックのシミュレーションに使用されます。

3:MyLocalTime()関数は、TIMERタイマーの累積秒数を現在の時間(年、月、日、時、分、秒)に変換します。時間を取得する必要がある場合は、この関数を呼び出します。

/*******************************************************************************
 * Function Name  : MyMakeTime
 * Description    : Form a 32 bit second counting value from calendar.
 * Input          : pointer to a calendar struct
 * Return         : 32 bit second counting value
 *******************************************************************************/
uint32_t MyMakeTime(Calendar_TypeDef *pCalendar)
{
    
    
  uint32_t TotalSeconds = pCalendar->sec;
  int16_t nYear = pCalendar->year;
  int16_t DaysInYear = 365;
  int16_t nMonth = pCalendar->month;
  int16_t DaysInMonth = 30;

  if((nYear < START_YEAR) || (nYear > (START_YEAR + 135))) 
    return 0;//out of year range

  TotalSeconds += (uint32_t)pCalendar->min * 60;//contribution of minutes
  TotalSeconds += (uint32_t)pCalendar->hour * 3600;//contribution of hours
  //contribution of mdays
  TotalSeconds += (uint32_t)(pCalendar->mday - 1) * SEC_IN_DAY;

  while(nMonth > 1)//contribution of months
  {
    
    
    nMonth --;
    if(nMonth == 1||nMonth == 3||nMonth == 5||nMonth == 7
        ||nMonth == 8||nMonth == 10||nMonth == 12)
      DaysInMonth = 31;
    else if(nMonth == 2)
    {
    
    
      if(IsLeapYear(nYear)) DaysInMonth = 29;
      else DaysInMonth = 28;
    }
    else DaysInMonth = 30;

    TotalSeconds += (uint32_t)DaysInMonth * SEC_IN_DAY;
  }

  while(nYear > START_YEAR)//contribution of years
  {
    
    
    nYear --;
    if(IsLeapYear(nYear)) DaysInYear = 366;
    else DaysInYear = 365;

    TotalSeconds += (uint32_t)DaysInYear * SEC_IN_DAY;
  }

  return TotalSeconds;
} 
//end function MyMakeTime

/*******************************************************************************
 * Function Name  : MyLocalTime
 * Description    : Form a calendar from 32 bit second counting.
 * Input          : pointer to a 32 bit second value
 * Return         : Calendar structure
 *******************************************************************************/
Calendar_TypeDef MyLocalTime(const uint32_t *pTotalSeconds)
{
    
    
  Calendar_TypeDef Calendar;
  uint32_t TotalDays, RemainSeconds;
  int16_t DaysInYear=365;
  int16_t DaysInMonth=30;

  Calendar.year = START_YEAR;
  Calendar.month = 1;  Calendar.mday = 1;
  Calendar.yday = 1;  
  Calendar.wday = Ymd2Wday(START_YEAR, 1, 1);



  TotalDays = *pTotalSeconds / SEC_IN_DAY;
  RemainSeconds = *pTotalSeconds % SEC_IN_DAY;
  Calendar.hour = (int16_t)(RemainSeconds / 3600);//calculate hour
  Calendar.min = (int16_t)((RemainSeconds / 60) % 60);//calculate minute
  Calendar.sec = (int16_t)(RemainSeconds % 60);//calculate second
  Calendar.wday = (int16_t)((TotalDays + Calendar.wday) % 7);//calculate wday

  while(1)//calculate year
  {
    
    
    if(IsLeapYear(Calendar.year)) DaysInYear = 366;
    else DaysInYear = 365;

    if(TotalDays >= DaysInYear)
    {
    
    
      TotalDays -= DaysInYear;
      Calendar.year ++;
    }//continue while
    else
      break;//forced to end while
  }//finish year calculation

  Calendar.yday += TotalDays;//calculate yday

  while(1)//calculate month
  {
    
    
    if(Calendar.month == 1||Calendar.month == 3||Calendar.month == 5
        ||Calendar.month == 7||Calendar.month == 8
        ||Calendar.month == 10||Calendar.month == 12)
      DaysInMonth = 31;
    else if(Calendar.month == 2)
    {
    
    
      if(IsLeapYear(Calendar.year)) DaysInMonth = 29;
      else DaysInMonth = 28;
    }
    else DaysInMonth = 30;

    if(TotalDays >= DaysInMonth)
    {
    
    
      TotalDays -= DaysInMonth;
      Calendar.month ++;
    }//continue while
    else
      break;//forced to end while
  }//finish month calculation

  Calendar.mday += (int16_t)TotalDays;//calculate mday

  return Calendar;
}
//end function MyLocalTime


/*******************************************************************************
 * Function Name  : Ymd2Wday
 * Description    : Calculate days in week from year, month, mday.
 * Input          : year, month, mday
 * Return         : 0--6, Suanday--Saturday
 *******************************************************************************/
static int16_t Ymd2Wday(int16_t nYear, int16_t nMonth, int16_t nMday)
{
    
     
  uint8_t i;
  const uint8_t DaysInMonth[] = {
    
    0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 }; 
  for(i = 0; i < nMonth; i++) nMday += DaysInMonth[i]; 
  if(nMonth > 2) 
  {
    
    
    if(IsLeapYear(nYear)) nMday++; 
  } 
  nYear--;
  return (nYear + nYear/4 - nYear/100 + nYear/400 + nMday)%7; 
}  
//end function Ymd2Wday

/***********************************************************************
 * Function Name  : IsLeapYear
 * Description    : Check whether the past year is leap or not.
 * Input          : 4 digits year number
 * Return         : 1: leap year. 0: not leap year
 ***********************************************************************/
static  uint8_t   IsLeapYear(int16_t nYear)
{
    
    
  if(nYear % 4 != 0)      return 0;
  if(nYear % 100 != 0)    return 1;
  return (uint8_t)(nYear % 400 == 0);
}
//end function IsLeapYear

要約:
1:この方法を使用して時間を正確に計時します。これは、RTCクロックソースとしての内部低速クロックLSIよりも正確です。
2:移植性が高く、タイマーを開くだけで秒数を積算できます。
3:時間調整が可能なアプリケーション環境に適しています。

おすすめ

転載: blog.csdn.net/zhuhongyan008/article/details/108604137