255 lines
6.5 KiB
C
255 lines
6.5 KiB
C
#include "stdint.h"
|
|
#include "FreeRTOS.h"
|
|
#include "task.h"
|
|
#include "rtc.h"
|
|
|
|
_calendar_obj calendar;
|
|
|
|
|
|
uint8_t const table_week[12] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
|
|
const uint8_t mon_table[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
|
|
|
/*********************************************************************
|
|
* @fn RTC_NVIC_Config
|
|
*
|
|
* @brief Initializes RTC Int.
|
|
*
|
|
* @return none
|
|
*/
|
|
void RTC_NVIC_Config (void) {
|
|
NVIC_InitTypeDef NVIC_InitStructure = {0};
|
|
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
|
|
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
|
|
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
|
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
|
NVIC_Init (&NVIC_InitStructure);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn Is_Leap_Year
|
|
*
|
|
* @brief Judging whether it is a leap year.
|
|
*
|
|
* @param year
|
|
*
|
|
* @return 1 - Yes
|
|
* 0 - No
|
|
*/
|
|
uint8_t Is_Leap_Year (u16 year) {
|
|
if (year % 4 == 0) {
|
|
if (year % 100 == 0) {
|
|
if (year % 400 == 0)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
} else
|
|
return 1;
|
|
} else
|
|
return 0;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn RTC_Set
|
|
*
|
|
* @brief Set Time.
|
|
*
|
|
* @param Struct of _calendar_obj
|
|
*
|
|
* @return 1 - error
|
|
* 0 - success
|
|
*/
|
|
uint8_t RTC_Set (u16 syear, uint8_t smon, uint8_t sday, uint8_t hour, uint8_t min, uint8_t sec) {
|
|
u16 t;
|
|
u32 seccount = 0;
|
|
if (syear < 1970 || syear > 2099)
|
|
return 1;
|
|
for (t = 1970; t < syear; t++) {
|
|
if (Is_Leap_Year (t))
|
|
seccount += 31622400;
|
|
else
|
|
seccount += 31536000;
|
|
}
|
|
smon -= 1;
|
|
for (t = 0; t < smon; t++) {
|
|
seccount += (u32)mon_table[t] * 86400;
|
|
if (Is_Leap_Year (syear) && t == 1)
|
|
seccount += 86400;
|
|
}
|
|
seccount += (u32)(sday - 1) * 86400;
|
|
seccount += (u32)hour * 3600;
|
|
seccount += (u32)min * 60;
|
|
seccount += sec;
|
|
|
|
RCC_APB1PeriphClockCmd (RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
|
|
PWR_BackupAccessCmd (ENABLE);
|
|
RTC_SetCounter (seccount);
|
|
RTC_WaitForLastTask();
|
|
return 0;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn RTC_Alarm_Set
|
|
*
|
|
* @brief Set Alarm Time.
|
|
*
|
|
* @param Struct of _calendar_obj
|
|
*
|
|
* @return 1 - error
|
|
* 0 - success
|
|
*/
|
|
uint8_t RTC_Alarm_Set (u16 syear, uint8_t smon, uint8_t sday, uint8_t hour, uint8_t min, uint8_t sec) {
|
|
u16 t;
|
|
u32 seccount = 0;
|
|
if (syear < 1970 || syear > 2099)
|
|
return 1;
|
|
for (t = 1970; t < syear; t++) {
|
|
if (Is_Leap_Year (t))
|
|
seccount += 31622400;
|
|
else
|
|
seccount += 31536000;
|
|
}
|
|
smon -= 1;
|
|
for (t = 0; t < smon; t++) {
|
|
seccount += (u32)mon_table[t] * 86400;
|
|
if (Is_Leap_Year (syear) && t == 1)
|
|
seccount += 86400;
|
|
}
|
|
seccount += (u32)(sday - 1) * 86400;
|
|
seccount += (u32)hour * 3600;
|
|
seccount += (u32)min * 60;
|
|
seccount += sec;
|
|
|
|
RCC_APB1PeriphClockCmd (RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
|
|
PWR_BackupAccessCmd (ENABLE);
|
|
RTC_SetAlarm (seccount);
|
|
RTC_WaitForLastTask();
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn RTC_Get_Week
|
|
*
|
|
* @brief Get the current day of the week.
|
|
*
|
|
* @param year/month/day
|
|
*
|
|
* @return week
|
|
*/
|
|
uint8_t RTC_Get_Week (u16 year, uint8_t month, uint8_t day) {
|
|
u16 temp2;
|
|
uint8_t yearH, yearL;
|
|
|
|
yearH = year / 100;
|
|
yearL = year % 100;
|
|
if (yearH > 19)
|
|
yearL += 100;
|
|
temp2 = yearL + yearL / 4;
|
|
temp2 = temp2 % 7;
|
|
temp2 = temp2 + day + table_week[month - 1];
|
|
if (yearL % 4 == 0 && month < 3)
|
|
temp2--;
|
|
return (temp2 % 7);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn RTC_Get
|
|
*
|
|
* @brief Get current time.
|
|
*
|
|
* @return 1 - error
|
|
* 0 - success
|
|
*/
|
|
uint8_t RTC_Get (void) {
|
|
static u16 daycnt = 0;
|
|
u32 timecount = 0;
|
|
u32 temp = 0;
|
|
u16 temp1 = 0;
|
|
timecount = RTC_GetCounter();
|
|
temp = timecount / 86400;
|
|
if (daycnt != temp) {
|
|
daycnt = temp;
|
|
temp1 = 1970;
|
|
while (temp >= 365) {
|
|
if (Is_Leap_Year (temp1)) {
|
|
if (temp >= 366)
|
|
temp -= 366;
|
|
else {
|
|
break;
|
|
}
|
|
} else
|
|
temp -= 365;
|
|
temp1++;
|
|
}
|
|
calendar.w_year = temp1;
|
|
temp1 = 0;
|
|
while (temp >= 28) {
|
|
if (Is_Leap_Year (calendar.w_year) && temp1 == 1) {
|
|
if (temp >= 29)
|
|
temp -= 29;
|
|
else
|
|
break;
|
|
} else {
|
|
if (temp >= mon_table[temp1])
|
|
temp -= mon_table[temp1];
|
|
else
|
|
break;
|
|
}
|
|
temp1++;
|
|
}
|
|
calendar.w_month = temp1 + 1;
|
|
calendar.w_date = temp + 1;
|
|
}
|
|
temp = timecount % 86400;
|
|
calendar.hour = temp / 3600;
|
|
calendar.min = (temp % 3600) / 60;
|
|
calendar.sec = (temp % 3600) % 60;
|
|
calendar.week = RTC_Get_Week (calendar.w_year, calendar.w_month, calendar.w_date);
|
|
return 0;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn RTC_Init
|
|
*
|
|
* @brief Initializes RTC collection.
|
|
*
|
|
* @return 1 - Init Fail
|
|
* 0 - Init Success
|
|
*/
|
|
uint8_t RTC_Init (void) {
|
|
uint8_t temp = 0;
|
|
RCC_APB1PeriphClockCmd (RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
|
|
PWR_BackupAccessCmd (ENABLE);
|
|
RTC_ClearITPendingBit (RTC_IT_ALR);
|
|
RTC_ClearITPendingBit (RTC_IT_SEC);
|
|
|
|
/* Is it the first configuration */
|
|
|
|
BKP_DeInit();
|
|
RCC_LSEConfig (RCC_LSE_ON);
|
|
while (RCC_GetFlagStatus (RCC_FLAG_LSERDY) == RESET && temp < 250) {
|
|
temp++;
|
|
vTaskDelay (pdMS_TO_TICKS (20));
|
|
}
|
|
if (temp >= 250)
|
|
return 1;
|
|
RCC_RTCCLKConfig (RCC_RTCCLKSource_LSE);
|
|
RCC_RTCCLKCmd (ENABLE);
|
|
RTC_WaitForLastTask();
|
|
RTC_WaitForSynchro();
|
|
RTC_ITConfig (RTC_IT_SEC, DISABLE);
|
|
RTC_ITConfig (RTC_IT_ALR, DISABLE);
|
|
RTC_ITConfig (RTC_IT_OW, DISABLE);
|
|
RTC_WaitForLastTask();
|
|
RTC_EnterConfigMode();
|
|
RTC_SetPrescaler (32767);
|
|
RTC_WaitForLastTask();
|
|
RTC_Set (2025, 9, 7, 11, 33, 30); /* Setup Time */
|
|
RTC_ExitConfigMode();
|
|
BKP_WriteBackupRegister (BKP_DR1, 0XA1A1);
|
|
|
|
RTC_NVIC_Config();
|
|
RTC_Get();
|
|
|
|
return 0;
|
|
} |