Use TIMER to simulate RTC clock

Use TIMER to simulate RTC clock

Borrow two functions in RTC.c in STM32F103 to realize RTC clock.
Advantages: strong portability and accurate timing.
Disadvantages: Need to adjust the time after each power on.
Applicable occasions: no external RTC crystal oscillator, time calibration.
Instructions for use:
1: First determine the time base: that is, what time is the starting point for calculation. We start at 0:00:00:00 on January 1, 2020, and the relevant definitions are as follows:

#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() calculates the time (year, month, day, hour, minute, and second) obtained through time calibration as the number of seconds from START_YEAR. The MyMakeTime function is only called once when obtaining the time calibration time issued by the host computer.
Put the number of seconds returned by the MyMakeTime function in the TIMER timer interrupt and accumulate once per second. Used to simulate the RTC clock.

3: The MyLocalTime() function converts the accumulated seconds of the TIMER timer into the current time: year, month, day, hour, minute, and second. When you need to get the time, just call this function.

/*******************************************************************************
 * 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

Summary:
1: Use this method to time the time accurately, which is more accurate than the internal low-speed clock LSI as the RTC clock source.
2: Portability is strong, only need to open a timer to accumulate the number of seconds.
3: It is suitable for the application environment where the time can be adjusted.

Guess you like

Origin blog.csdn.net/zhuhongyan008/article/details/108604137