Utilice TIMER para simular el reloj RTC

Utilice TIMER para simular el reloj RTC

Tome prestadas dos funciones en RTC.c en STM32F103 para realizar el reloj RTC.
Ventajas: portabilidad fuerte y sincronización precisa.
Desventajas: es necesario ajustar el tiempo después de cada encendido.
Ocasiones aplicables: sin oscilador de cristal RTC externo, calibración de tiempo.
Instrucciones de uso:
1: Primero determine la base de tiempo: es decir, qué hora es el punto de partida para el cálculo. Comenzamos a las 0: 00: 00: 00 el 1 de enero de 2020, y las definiciones relevantes son las siguientes:

#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 () calcula el tiempo (año, mes, día, hora, minuto y segundo) obtenido a través de la calibración de tiempo como el número de segundos de START_YEAR. La función MyMakeTime solo se llama una vez cuando se obtiene la hora de calibración de hora emitida por la computadora host.
Ponga el número de segundos devueltos por la función MyMakeTime en la interrupción del temporizador TIMER y acumule una vez por segundo. Se utiliza para simular el reloj RTC.

3: La función MyLocalTime () convierte los segundos acumulados del temporizador TIMER en la hora actual: año, mes, día, hora, minuto y segundo. Cuando necesite obtener la hora, simplemente llame a esta función.

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

Resumen:
1: Utilice este método para medir el tiempo con precisión, que es más preciso que el LSI del reloj interno de baja velocidad como fuente de reloj RTC.
2: La portabilidad es fuerte, solo es necesario abrir un temporizador para acumular la cantidad de segundos.
3: Es adecuado para el entorno de aplicación donde se puede ajustar el tiempo.

Supongo que te gusta

Origin blog.csdn.net/zhuhongyan008/article/details/108604137
Recomendado
Clasificación