N32L406C8芯片RTC基础应用驱动程序

RTC时钟采用外部32.768Khz外部晶振,RTC系统时间变量在定时器中断中每1秒更新一次( getRtc()),闹钟A中断用于芯片休眠唤醒,如果项目需求不一样,可以修改相关代码,以适应设计需求。另外,RTC的初始化时间,默认采用程序编译更新时间,原项目会在4G联网后获取网络时间,更新准确的RTC时间,也可以通过串口AT指令设置实时的RTC时间。同样,前面是头文件代码,后面是应用代码,代码实测。
#ifndef __RTC_H__
#define __RTC_H__

#include "main.h"

#define UTC_LEN  10


#define  BKP_DAT1     ((uint16_t)0x0000)
#define  BKP_DAT2     ((uint16_t)0x0004)
#define  BKP_DAT3     ((uint16_t)0x0008)
#define  BKP_DAT4     ((uint16_t)0x000C)
#define  BKP_DAT5     ((uint16_t)0x0010)
#define  BKP_DAT6     ((uint16_t)0x0014)
#define  BKP_DAT7     ((uint16_t)0x0018)
#define  BKP_DAT8     ((uint16_t)0x001C)
#define  BKP_DAT9     ((uint16_t)0x0020)
#define  BKP_DAT10    ((uint16_t)0x0024)
#define  BKP_DAT11    ((uint16_t)0x0028)
#define  BKP_DAT12    ((uint16_t)0x002C)
#define  BKP_DAT13    ((uint16_t)0x0030)
#define  BKP_DAT14    ((uint16_t)0x0034)
#define  BKP_DAT15    ((uint16_t)0x0038)
#define  BKP_DAT16    ((uint16_t)0x003C)
#define  BKP_DAT17    ((uint16_t)0x0040)
#define  BKP_DAT18    ((uint16_t)0x0044)
#define  BKP_DAT19    ((uint16_t)0x0048)
#define  BKP_DAT20    ((uint16_t)0x004C)

#define  IS_BKP_DAT(DAT)                                                                                    \
             (((DAT) == BKP_DAT1)  || ((DAT) == BKP_DAT2)  || ((DAT) == BKP_DAT3)  || ((DAT) == BKP_DAT4)   \
           || ((DAT) == BKP_DAT5)  || ((DAT) == BKP_DAT6)  || ((DAT) == BKP_DAT7)  || ((DAT) == BKP_DAT8)   \
           || ((DAT) == BKP_DAT9)  || ((DAT) == BKP_DAT10) || ((DAT) == BKP_DAT11) || ((DAT) == BKP_DAT12)  \
           || ((DAT) == BKP_DAT13) || ((DAT) == BKP_DAT14) || ((DAT) == BKP_DAT15) || ((DAT) == BKP_DAT16)  \
           || ((DAT) == BKP_DAT17) || ((DAT) == BKP_DAT18) || ((DAT) == BKP_DAT19) || ((DAT) == BKP_DAT20) )

#define  BACKUP_REGISTER_SIZE        20

#define    USER_WRITE_BKP_DAT1_DATA       0xA1A1

#define    RTC_ALARM_TEST_TYPE_IRQ        0x01
#define    RTC_ALARM_TEST_TYPE_OUTPUT     0x02
#define    RTC_ALARM_TEST_TYPE            RTC_ALARM_TEST_TYPE_IRQ

#define    RTC_ALARM_OUT_TYPE_OPEN_DRAIN  0x01
#define    RTC_ALARM_OUT_TYPE_PULL_PUSH   0x02
#define    RTC_ALARM_OUT_TYPE             RTC_ALARM_OUT_TYPE_PULL_PUSH
#define    RTC_LSE_TRY_COUNT              250

typedef enum {
    RTC_CLK_SRC_TYPE_HSE_DIV32=0x01,
    RTC_CLK_SRC_TYPE_LSE=0x02,
    RTC_CLK_SRC_TYPE_LSI=0x03,
}RTC_CLK_SRC_TYPE;


extern RTC_DateType rtcDateDefault;  //RTC date default value

extern RTC_DateType rtcDate;
extern RTC_DateType rtcSetData;

extern RTC_TimeType rtcTime;
extern RTC_TimeType rtcSetTime;

extern RTC_AlarmType alarmSet;

//时区         时区范围         时区中心线            
//UTC          7.5°W~7.5°E      0°
//UTC+1        7.5°E~22.5°E     15°E
//UTC+2        22.5°E~37.5°E    30°E
//UTC+3        37.5°E~52.5°E    45°E
//UTC+4        52.5°E~67.5°E    60°E
//UTC+5        67.5°E~82.5°E    75°E
//UTC+6        82.5°E~97.5°E    90°E
//UTC+7        97.5°E~112.5°E   105°E
//UTC+8        112.5°E~127.5°E  120°E
//UTC+9        127.5°E~142.5°E  135°E
//UTC+10       142.5°E~157.5°E  150°E
//UTC+11       157.5°E~172.5°E  165°E
//东西十二区   172.5°E~172.5°W  180°
//UTC-11       172.5°W~157.5°W  165°W
//UTC-10       157.5°W~142.5°W  150°W
//UTC-9        142.5°W~127.5°W  135°W
//UTC-8        127.5°W~112.5°W  120°W
//UTC-7        112.5°W~97.5°W   105°W
//UTC-6        97.5°W~82.5°W    90°W
//UTC-5        82.5°W~67.5°W    75°W
//UTC-4        67.5°W~52.5°W    60°W
//UTC-3        52.5°W~37.5°W    45°W
//UTC-2        37.5°W~22.5°W    30°W
//UTC-1        22.5°W~7.5°W     15°W    


struct __RTC__
{    
    s8  utc;       //时区 
  s16 offSet;    //时区偏差精确到秒,32768/60/60 = 9.1小时,时区偏差正负1小时之内
    s16 offsetY;   //年基数,RTC年份只有后两位,所以要加上2000.
     
    uint8_t year;  
    uint8_t month; 
    uint8_t date;    
    uint8_t weekDay;     
    uint8_t hours;  
  uint8_t minutes;  
  uint8_t seconds;     
  char     H12;        //AM:上午  PM:下午    
    char setTime;         //时间设置
    char setDate;
    char utcSet;    
    char initialOk;
    char debug;
};

extern struct __RTC__ rtc;            //RTC data
extern struct __RTC__ agpsRtc;
extern struct __RTC__ resetRtc;
extern struct __RTC__ heartbeatRtc;
extern struct __RTC__ positionRepotRtc;
extern struct __RTC__ positionRepotReadyRtc;
extern struct __RTC__ sleepRtc;   //工作模式中休眠时间,RTC控制变量
extern struct __RTC__ chargeRtc;

u8 weekDay(u8 year,u8 month,u8 day);
void rtcInit(void);       //   RTC initial
void rtcDeal(void);  //RTC处理
void WakeUpClockSelect(uint8_t WKUPClkSrcSel);
void EXTI20_RTCWKUP_Configuration(FunctionalState Cmd);
void addSeconds(RTC_AlarmType *alarmTime,struct __RTC__ currentRtc,u32 seconds);        //
void addSecondsRTC(struct __RTC__ *resultRtc,struct __RTC__ currentRtc,u32 seconds);    //
void subSencondsRtc(struct __RTC__ *resultRtc,struct __RTC__ rtc,u32 seconds);
s32 subRtc(struct __RTC__ rtc1,struct __RTC__ rtc2);                                  //return seconds = rtc1-rtc2;

void getRtc(void); //获取RTC时间
void setAarmTime(uint8_t year,uint8_t month,uint8_t day,uint8_t hours,uint8_t minutes,uint8_t seconds);

void setAlarmA(RTC_AlarmType* alarmSet);  //set alarm a wake up time
#endif

#include "rtc.h"


//__DATE__ 当前日期,一个以 “MMM DD YYYY” 格式表示的字符串常量。
//__TIME__ 当前时间,一个以 “HH:MM:SS” 格式表示的字符串常量。
//__FILE__ 这会包含当前文件名,一个字符串常量。
//__LINE__ 这会包含当前行号,一个十进制常量。
//__STDC__ 当编译器以 ANSI 标准编译时,则定义为 1;判断该文件是不是标准 C 程序。

//struct __Timep  GET_TIM;

RTC_DateType rtcDateDefault;  //RTC date default value
RTC_DateType rtcDate;
RTC_DateType rtcSetData;

RTC_TimeType rtcTimeDefault;  //RTC time default value
RTC_TimeType rtcTime;
RTC_TimeType rtcSetTime;

RTC_AlarmType alarmSet;

struct __RTC__ rtc;
struct __RTC__ agpsRtc;
struct __RTC__ resetRtc;
struct __RTC__ heartbeatRtc;
struct __RTC__ positionRepotRtc;
struct __RTC__ positionRepotReadyRtc;
struct __RTC__ sleepRtc;   //工作模式中休眠时间,RTC控制变量
struct __RTC__ chargeRtc;
RTC_InitType  RTC_InitStructure;
uint32_t SynchPrediv, AsynchPrediv;

void BKP_WriteBkpData(uint32_t BKP_DAT, uint32_t Data)
{
    __IO uint32_t tmp = 0;
    /* Check the parameters */
    assert_param(IS_BKP_DAT(BKP_DAT));
    tmp = (uint32_t)&RTC->BKP1R;
    tmp += BKP_DAT;
    *(__IO uint32_t*)tmp = Data;
}
uint32_t BKP_ReadBkpData(uint32_t BKP_DAT)
{
    __IO uint32_t tmp = 0;
    uint32_t value = 0;
    /* Check the parameters */
    assert_param(IS_BKP_DAT(BKP_DAT));
    tmp = (uint32_t)&RTC->BKP1R;
    tmp += BKP_DAT;
    value = (*(__IO uint32_t*)tmp);
    return value;
}


void RTC_PrescalerConfig(void)
{
    /* Configure the RTC data register and RTC prescaler */
    RTC_InitStructure.RTC_AsynchPrediv = AsynchPrediv;
    RTC_InitStructure.RTC_SynchPrediv  = SynchPrediv;
    RTC_InitStructure.RTC_HourFormat   = RTC_24HOUR_FORMAT;
    /* Check on RTC init */
    if (RTC_Init(&RTC_InitStructure) == ERROR)
    {
        // debugLog("\r\n //******* RTC Prescaler Config failed **********// \r\n");
    }
}

// /**
//  * @brief  Configures the RTC Source Clock Type.
//  * @param Clk_Src_Type specifies RTC Source Clock Type.
//  *   This parameter can be on of the following values:
//  *     @arg RTC_CLK_SRC_TYPE_HSE128
//  *     @arg RTC_CLK_SRC_TYPE_LSE
//  *     @arg RTC_CLK_SRC_TYPE_LSI
//  * @param Is_First_Cfg_RCC specifies Is First Config RCC Module.
//  *   This parameter can be on of the following values:
//  *     @arg true
//  *     @arg false
//  * @return An ErrorStatus enumeration value:
//  *          - SUCCESS: RTC clock configure success
//  *          - ERROR: RTC clock configure failed
//  */
ErrorStatus RTC_CLKSourceConfig(RTC_CLK_SRC_TYPE Clk_Src_Type, bool Is_First_Cfg_RCC)
{
  uint8_t lse_ready_count=0;
  ErrorStatus Status=SUCCESS;
  
  RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_PWR, ENABLE);    //Enable the PWR clock
  RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
  /* Allow access to RTC */
  PWR_BackupAccessEnable(ENABLE);
  /* Disable RTC clock */
  RCC_EnableRtcClk(DISABLE);
  // User_Delay_init();
  if (RTC_CLK_SRC_TYPE_HSE_DIV32 == Clk_Src_Type)
  {
    // debugLog("\r\n RTC_ClkSrc Is Set HSE/32! \r\n");
    if (true == Is_First_Cfg_RCC )
    {
        /* Enable HSE */
        RCC_EnableLsi(DISABLE);
        RCC_ConfigHse(RCC_HSE_ENABLE);
        while (RCC_WaitHseStable() == ERROR)
        {
        }
        RCC_ConfigRtcClk(RCC_RTCCLK_SRC_HSE_DIV32);
    }
    else
    {
        RCC_EnableLsi(DISABLE);
        RCC_ConfigRtcClk(RCC_RTCCLK_SRC_HSE_DIV32);
        /* Enable HSE */
        RCC_ConfigHse(RCC_HSE_ENABLE);
        while (RCC_WaitHseStable() == ERROR)
        {
        }
    }
    SynchPrediv  = 0x7A0; // 8M/32 = 250KHz
    AsynchPrediv = 0x7F;  // value range: 0-7F
  }
  else if (RTC_CLK_SRC_TYPE_LSE == Clk_Src_Type)
  {
    // debugLog("\r\n RTC_ClkSrc Is Set LSE! \r\n");
    if (true == Is_First_Cfg_RCC)
    {
      /* Enable the LSE OSC32_IN PC14 */
      RCC_EnableLsi(DISABLE); // LSI is turned off here to ensure that only one clock is turned on
      #if (_TEST_LSE_BYPASS_)
      RCC_ConfigLse(RCC_LSE_BYPASS,0x1FF);
      #else
      RCC_ConfigLse(RCC_LSE_ENABLE,0x1FF);
      #endif
      lse_ready_count=0;
      /****Waite LSE Ready *****/
      while((RCC_GetFlagStatus(RCC_LDCTRL_FLAG_LSERD) == RESET) && (lse_ready_count<RTC_LSE_TRY_COUNT))
      {
        lse_ready_count++;
        delay_ms(10);
        /****LSE Ready failed or timeout*****/
        if(lse_ready_count>=RTC_LSE_TRY_COUNT)
        {
          Status = ERROR;
          // debugLog("\r\n RTC_ClkSrc Set LSE Faile! \r\n");
          break;
        }
      }
      RCC_ConfigRtcClk(RCC_RTCCLK_SRC_LSE);
    }
    else
    {
      /* Enable the LSE OSC32_IN PC14 */
      RCC_EnableLsi(DISABLE);
      RCC_ConfigRtcClk(RCC_RTCCLK_SRC_LSE);
      #if (_TEST_LSE_BYPASS_)
      RCC_ConfigLse(RCC_LSE_BYPASS,0x1FF);
      #else
      RCC_ConfigLse(RCC_LSE_ENABLE,0x1FF);
      #endif
      lse_ready_count=0;
      /****Waite LSE Ready *****/
      while((RCC_GetFlagStatus(RCC_LDCTRL_FLAG_LSERD) == RESET) && (lse_ready_count<RTC_LSE_TRY_COUNT))
      {
        lse_ready_count++;
        delay_ms(10);
        /****LSE Ready failed or timeout*****/
        if(lse_ready_count>=RTC_LSE_TRY_COUNT)
        {
          Status = ERROR;
          //  debugLog("\r\n RTC_ClkSrc Set LSE Faile! \r\n");
          break;
        }
      }
    }
    SynchPrediv  = 0xFF; // 32.768KHz
    AsynchPrediv = 0x7F; // value range: 0-7F
  }
  else if (RTC_CLK_SRC_TYPE_LSI == Clk_Src_Type)
  {
    // debugLog("\r\n RTC_ClkSrc Is Set LSI! \r\n");
    if (true == Is_First_Cfg_RCC)
    {
      /* Enable the LSI OSC */
      RCC_EnableLsi(ENABLE);
      while (RCC_GetFlagStatus(RCC_CTRLSTS_FLAG_LSIRD) == RESET)
      {
      }
      RCC_ConfigRtcClk(RCC_RTCCLK_SRC_LSI);
    }
    else
    {
      RCC_ConfigRtcClk(RCC_RTCCLK_SRC_LSI);
      /* Enable the LSI OSC */
      RCC_EnableLsi(ENABLE);
      while (RCC_GetFlagStatus(RCC_CTRLSTS_FLAG_LSIRD) == RESET)
        {
        }
    }
    SynchPrediv  = 0x14A; // 41828Hz
    AsynchPrediv = 0x7F;  // value range: 0-7F
  }
  else
  {
      // debugLog("\r\n RTC_ClkSrc Value is error! \r\n");
  }
  /* Enable the RTC Clock */
  RCC_EnableRtcClk(ENABLE);
  RTC_WaitForSynchro();
  return Status;
}

//利用基姆拉尔森计算公式由年月日,计算出星期几。
//W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400) mod 7
u8 weekDay(u8 year,u8 month,u8 day)
{
    u8 WeekDay = 0;
    WeekDay=(day+1+2*month+3*(month+1)/5+year+year/4-year/100+year/400)%7;
    if(WeekDay == 0) WeekDay = 7;
    return WeekDay;
}
void setDefaultRtcParameter(void)  //RTC default data timer
{
    u16 testYear = 0;
    char data[] = __DATE__;
    char time[] = __TIME__;
    if(strstr(data,"Jan")!=NULL) //if(data[0] == 'J'&&data[1] == 'a'&&data[2] == 'n')  //months
    {
        rtcDateDefault.Month = 1;        
    }
    else if(strstr(data,"Feb")!=NULL) //else if(data[0] == 'F'&&data[1] == 'e'&&data[2] == 'b')
    {
        rtcDateDefault.Month = 2;        
    }
    else if(strstr(data,"Mar")!=NULL) //else if(data[0] == 'M'&&data[1] == 'a'&&data[2] == 'r')
    {
        rtcDateDefault.Month = 3;        
    }
    else if(strstr(data,"Apr")!=NULL) //else if(data[0] == 'A'&&data[1] == 'p'&&data[2] == 'r')
    {
        rtcDateDefault.Month = 4;        
    }
    else if(strstr(data,"May")!=NULL) //if(data[0] == 'M'&&data[1] == 'a'&&data[2] == 'y')
    {
        rtcDateDefault.Month = 5;        
    }
    else if(strstr(data,"Jun")!=NULL) //if(data[0] == 'J'&&data[1] == 'u'&&data[2] == 'n')
    {
        rtcDateDefault.Month = 6;        
    }
    else if(strstr(data,"Jul")!=NULL) //if(data[0] == 'J'&&data[1] == 'u'&&data[2] == 'l')
    {
        rtcDateDefault.Month = 7;        
    }
    else if(strstr(data,"Aug")!=NULL) //if(data[0] == 'A'&&data[1] == 'u'&&data[2] == 'g')
    {
        rtcDateDefault.Month = 8;        
    }
    else if(strstr(data,"Sep")!=NULL) //if(data[0] == 'S'&&data[1] == 'e'&&data[2] == 'p')
    {
        rtcDateDefault.Month = 9;        
    }
    else if(strstr(data,"Oct")!=NULL) //if(data[0] == 'O'&&data[1] == 'c'&&data[2] == 't')
    {
        rtcDateDefault.Month = 10;        
    }
    else if(strstr(data,"Nov")!=NULL) //if(data[0] == 'N'&&data[1] == 'o'&&data[2] == 'v')
    {
        rtcDateDefault.Month = 11;        
    }
    else if(strstr(data,"Dec")!=NULL) //if(data[0] == 'D'&&data[1] == 'e'&&data[2] == 'c')
    {
        rtcDateDefault.Month = 12;        
    }
    
    rtcDateDefault.Date  = (data[4]&0x0f)*10+(data[5]&0x0f);                                            //day
    //rtcDateDefault.Year  = (data[7]&0x0f)*1000+(data[8]&0x0f)*100+(data[9]&0x0f)*10+(data[10]&0x0f);  //year    
    testYear = (data[7]&0x0f)*1000+(data[8]&0x0f)*100+(data[9]&0x0f)*10+(data[10]&0x0f);  //year    
    if(rtc.debug) debugLog("testYear = %d,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,\n",testYear);
    rtcDateDefault.Year  = (data[9]&0x0f)*10+(data[10]&0x0f);  //year 这里只能区十分位和各位计算。


    rtcDateDefault.WeekDay = weekDay(rtcDateDefault.Year,rtcDateDefault.Month,rtcDateDefault.Date);

    rtcTimeDefault.Hours   = (time[0]&0x0f)*10+(time[1]&0x0f);      //Hours
    rtcTimeDefault.Minutes = (time[3]&0x0f)*10+(time[4]&0x0f);      //Minutes    
    rtcTimeDefault.Seconds = (time[6]&0x0f)*10+(time[7]&0x0f);      //Seconds    
    
    rtc.utc = 0;              //默认北京时间,东八区    
    rtc.offSet = 0;           //时差
    rtc.offSet = 0;         //This code just for testing.

    rtc.offsetY = (data[7]&0x0f)*1000+(data[8]&0x0f)*100; 
    
  //rtc.debug = DEBUG_ENABLE;
    rtc.debug = DEBUG_DISABLE;    
}
void rtcInit(void)  //RTC initial
{        
    
  /* RTC date time alarm default value*/
  setDefaultRtcParameter();
  /* Enable the PWR clock */
  RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_PWR, ENABLE);
  /* Allow access to RTC */
  PWR_BackupAccessEnable(ENABLE);
  if (USER_WRITE_BKP_DAT1_DATA != BKP_ReadBkpData(BKP_DAT1) )
  {
    /* RTC clock source select */
    if(SUCCESS==RTC_CLKSourceConfig(RTC_CLK_SRC_TYPE_LSE, true))
    {
      /* RTC clock source select */
      RTC_CLKSourceConfig(RTC_CLK_SRC_TYPE_LSE, true);
      RTC_PrescalerConfig();
      /* RTC date time and alarm regulate*/
      //  RTC_DateRegulate();
      //  RTC_TimeRegulate();
      RTC_SetDate(RTC_FORMAT_BIN, &rtcDateDefault);
      RTC_ConfigTime(RTC_FORMAT_BIN, &rtcTimeDefault);        
      //  RTC_AlarmRegulate(RTC_A_ALARM);
      BKP_WriteBkpData(BKP_DAT1, USER_WRITE_BKP_DAT1_DATA);
      //  debugLog("\r\n RTC Init Success\r\n");
    }
    else
    {
      //  debugLog("\r\n RTC Init Faile\r\n");
    }
  }
  getRtc(); //获取RTC时间        
  /* Alarm out select option*/

  // RTC_ClrIntPendingBit(RTC_INT_ALRA);
  // EXTI18_RTCAlarm_Configuration(ENABLE);        
}
// void WakeUpClockSelect(uint8_t WKUPClkSrcSel)
// {
//     if (WKUPClkSrcSel == 0x01)
//         RTC_ConfigWakeUpClock(RTC_WKUPCLK_RTCCLK_DIV16);
//     else if (WKUPClkSrcSel == 0x02)
//         RTC_ConfigWakeUpClock(RTC_WKUPCLK_RTCCLK_DIV8);
//     else if (WKUPClkSrcSel == 0x03)
//         RTC_ConfigWakeUpClock(RTC_WKUPCLK_RTCCLK_DIV4);
//     else if (WKUPClkSrcSel == 0x04)
//         RTC_ConfigWakeUpClock(RTC_WKUPCLK_RTCCLK_DIV2);
//     else if (WKUPClkSrcSel == 0x05)
//         RTC_ConfigWakeUpClock(RTC_WKUPCLK_CK_SPRE_16BITS);    
// }
// void EXTI20_RTCWKUP_Configuration(FunctionalState Cmd)
// {
//     EXTI_InitType EXTI_InitStructure;
//     NVIC_InitType NVIC_InitStructure;

//     EXTI_ClrITPendBit(EXTI_LINE20);
//     EXTI_InitStructure.EXTI_Line = EXTI_LINE20;
//     #ifdef __TEST_SEVONPEND_WFE_NVIC_DIS__
//         EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
//     #else
//         EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
//     #endif
//     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
//     EXTI_InitStructure.EXTI_LineCmd = ENABLE;
//     EXTI_InitPeripheral(&EXTI_InitStructure);
//     /* Enable the RTC WakeUp Interrupt */
//     NVIC_InitStructure.NVIC_IRQChannel                   = RTC_IRQn;
//     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
//     NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
//     NVIC_InitStructure.NVIC_IRQChannelCmd                = Cmd;
//     NVIC_Init(&NVIC_InitStructure);
// }
void addSeconds(RTC_AlarmType *alarmTime,struct __RTC__ currentRtc,u32 seconds)    //
{
    u32 temp = 0;    
    u32 tempS = 0;  //seconds
    u32 tempM = 0;  //minutes
    u32 tempH = 0;  //hours
    u32 tempD = 0;  //day    
    tempS = (currentRtc.seconds+seconds)%60;  
    tempM = (currentRtc.seconds+seconds)/60;
    //newRtcTime->Seconds = tempS; //
    alarmTime->AlarmTime.Seconds = tempS;
    temp =  (tempM+currentRtc.minutes)%60;
    tempH = (tempM+currentRtc.minutes)/60;
    //newRtcTime->Minutes = temp;
    alarmTime->AlarmTime.Minutes = temp;
    temp  = (tempH+currentRtc.hours)%24;
    tempD = (tempH+currentRtc.hours)/24;    
    //newRtcTime->Hours = temp;    //确保小时不超过24
    alarmTime->AlarmTime.Hours = temp;    //;    
    alarmTime->DateWeekValue = (currentRtc.date +tempD);    
    alarmTime->AlarmMask        =  RTC_ALARMMASK_WEEKDAY;    
}
void addSecondsRTC(struct __RTC__ *resultRtc,struct __RTC__ currentRtc,u32 seconds)    //
{
    u32 temp = 0;    
    u32 tempS = 0;  //seconds
    u32 tempM = 0;  //minutes
    u32 tempH = 0;  //hours
    u32 tempD = 0;  //day    
    tempS = (currentRtc.seconds+seconds)%60;  
    tempM = (currentRtc.seconds+seconds)/60;
    //newRtcTime->Seconds = tempS; //
    resultRtc->seconds = tempS;
    temp =  (tempM+currentRtc.minutes)%60;
    tempH = (tempM+currentRtc.minutes)/60;
    //newRtcTime->Minutes = temp;
    resultRtc->minutes = temp;
    temp = (tempH+currentRtc.hours)%24;
    tempD = (tempH+currentRtc.hours)/24;    
    //newRtcTime->Hours = temp;    //确保小时不超过24
    resultRtc->hours = temp;    //;    
    resultRtc->date = (currentRtc.date +tempD);            
}
void subSencondsRtc(struct __RTC__ *resultRtc,struct __RTC__ rtc,u32 seconds)
{
    u32 tempValue = 0;
    u32 tempHours = 0;
    u32 tempMinutes = 0;
    // u32 tempSeconds = 0;
    tempValue = rtc.hours*60*60+rtc.minutes*60+rtc.seconds;
    if(tempValue>=seconds)
    {
        tempValue = tempValue - seconds;        
    }
    else
    {
        tempValue = 86400+tempValue-seconds;        
    }
    resultRtc->seconds = tempValue%60;
    tempMinutes = tempValue/60; //
    resultRtc-> minutes = tempMinutes%60;
    tempHours = tempMinutes/60;
    resultRtc->hours = tempHours/24;
}
s32 subRtc(struct __RTC__ rtc1,struct __RTC__ rtc2) //return seconds = rtc1-rtc2;
{
    s32 seconds = 0;
    s32 tempValue1 = rtc1.hours*60*60+rtc1.minutes*60+rtc1.seconds;
    s32 tempValue2 = rtc2.hours*60*60+rtc2.minutes*60+rtc2.seconds;
    if(rtc1.date == rtc2.date) seconds = tempValue1 -tempValue2;
    else seconds = 86400+tempValue1 -tempValue2;
    // seconds = tempValue1 -tempValue2;
    return seconds; //rtc1-rtc2
}
void setAarmTime(uint8_t year,uint8_t month,uint8_t day,uint8_t hours,uint8_t minutes,uint8_t seconds)

{
    alarmSet.DateWeekMode     =  RTC_ALARM_SEL_WEEKDAY_DATE;           //This code just for testing.
    //alarmSet.DateWeekMode     =  RTC_ALARM_SEL_WEEKDAY_WEEKDAY;           //
    if((0<day)&&(day<=31))
    {
        alarmSet.DateWeekValue    =  day;  
    }
    else
    {
        alarmSet.DateWeekValue    =  1;  
        debugLog("The alarm day is wrong.");
    }
    
    // alarmSet.AlarmMask        =  RTC_ALARMMASK_WEEKDAY | RTC_ALARMMASK_HOURS | RTC_ALARMMASK_MINUTES;
    alarmSet.AlarmMask        =  RTC_ALARMMASK_WEEKDAY;
    //alarmSet.AlarmTime.H12    =  rtcTime.H12;
    alarmSet.AlarmTime.Hours  = hours%24;
    alarmSet.AlarmTime.Minutes  = minutes%60;
    alarmSet.AlarmTime.Seconds  = seconds%60;    
}
void EXTI18_RTCAlarm_Configuration(FunctionalState Cmd)
{
    EXTI_InitType EXTI_InitStructure;
    NVIC_InitType NVIC_InitStructure;

    EXTI_ClrITPendBit(EXTI_LINE18);
    EXTI_InitStructure.EXTI_Line = EXTI_LINE18;
    #ifdef __TEST_SEVONPEND_WFE_NVIC_DIS__
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
    #else
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    #endif
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_InitPeripheral(&EXTI_InitStructure);

    /* Enable the RTC Alarm Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel                   = RTCAlarm_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = Cmd;
    NVIC_Init(&NVIC_InitStructure);
}
void  setAlarmA(RTC_AlarmType* alarmSet)  //set alarm A wake up time    

    //setAarmTime(23,4,17,13,59,00);    
    RTC_EnableAlarm(RTC_A_ALARM, DISABLE);  // Disable the Alarm A
    
    if((0<alarmSet->DateWeekValue)&&(alarmSet->DateWeekValue<=31))
    {
        alarmSet->DateWeekValue    =  alarmSet->DateWeekValue;  
    }
    else
    {
        alarmSet->DateWeekValue    =  1;  
        // debugLog("The alarm day is wrong.");
    }
    
    RTC_SetAlarm(RTC_FORMAT_BIN, RTC_A_ALARM, alarmSet);   //Configure the RTC Alarm A register 
    RTC_ConfigInt(RTC_INT_ALRA, ENABLE);                   //Enable the RTC Alarm A Interrupt
    RTC_EnableAlarm(RTC_A_ALARM, ENABLE);                  //Enable the alarm    
    EXTI18_RTCAlarm_Configuration(ENABLE);    
  
}
void RTCAlarm_IRQHandler(void)
{
    if (RTC_GetITStatus(RTC_INT_ALRA) != RESET)
    {       
        RTC_ClrIntPendingBit(RTC_INT_ALRA);
        EXTI_ClrITPendBit(EXTI_LINE18);
        sleep.wakeupSource =     WAKEUP_SOURCE_ALARM; //Alarm A wakeup.
        IWDG_ReloadKey(); //喂狗
    }
    // sleep.wakeupSource =     WAKEUP_SOURCE_ALARM; //Alarm A wakeup.
}
void getRtc(void) //获取RTC时间
{
    RTC_GetDate(RTC_FORMAT_BIN, &rtcDate);     //RTC date.
    RTC_GetTime(RTC_FORMAT_BIN, &rtcTime);   //RTC time.    
    rtc.year = rtcDate.Year;
    rtc.month = rtcDate.Month;
    rtc.date = rtcDate.Date;
    rtc.weekDay = rtcDate.WeekDay;
    rtc.hours = rtcTime.Hours;
    rtc.minutes = rtcTime.Minutes;
    rtc.seconds = rtcTime.Seconds;        
    (void)RTC->DATE;    //I don't know why. 
}    
void rtcDeal(void)  //RTC处理
{
    static u32 tempTime = 0;
    char buf[30] = {0};
    if(rtc.setTime == 1)  //Set the RTC time
    {    
        rtc.setTime = 0;        
        RTC_ConfigTime(RTC_FORMAT_BIN, &rtcSetTime);        
        // addSecondsRTC(&positionRepotRtc,rtc,parm.wMode[parm.currentMode].positionReportTimeLimit);    //计算下次位置上报时间
      // addSecondsRTC(&heartbeatRtc,rtc,parm.wMode[parm.currentMode].heartBeatTimeLimit);              //计算下次心跳时间
        // addSecondsRTC(&agpsRtc,rtc,AGPS_TIME);  //下次AGPS时间  
        addSecondsRTC(&resetRtc,rtc,parm.wkMode[parm.currentMode].resetTime);  //下次重启RTC时间          
    }
    if(rtc.setDate == 1)  //Set the RTC date.
    {
        rtc.setDate = 0;
        RTC_SetDate(RTC_FORMAT_BIN, &rtcSetData);         
    }    
}

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kevinpan2011

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值