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);
}
}