/********************************** (C) COPYRIGHT ******************************* * File Name : main.c * Author : WCH * Version : V1.0.0 * Date : 2021/06/06 * Description : Main program body. ********************************************************************************* * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. * Attention: This software (modified or not) and binary are used for * microcontroller manufactured by Nanjing Qinheng Microelectronics. *******************************************************************************/ /* *@Note *Calendar routine: *This routine demonstrates that the initial time is 13:58:55 on October 8, 2019, *real-time timing, every 1S through the serial port Print the real-time clock value. * */ #include "debug.h" /* Global define */ /* Global Variable */ typedef struct { vu8 hour; vu8 min; vu8 sec; vu16 w_year; vu8 w_month; vu8 w_date; vu8 week; } _calendar_obj; _calendar_obj calendar; u8 const table_week[12] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5}; const u8 mon_table[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; /* Exported_Functions */ u8 RTC_Init(void); u8 Is_Leap_Year(u16 year); u8 RTC_Alarm_Set(u16 syear, u8 smon, u8 sday, u8 hour, u8 min, u8 sec); u8 RTC_Get(void); u8 RTC_Get_Week(u16 year, u8 month, u8 day); u8 RTC_Set(u16 syear, u8 smon, u8 sday, u8 hour, u8 min, u8 sec); /********************************************************************* * @fn RTC_NVIC_Config * * @brief Initializes RTC Int. * * @return none */ static 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 RTC_Init * * @brief Initializes RTC collection. * * @return 1 - Init Fail * 0 - Init Success */ u8 RTC_Init(void) { u8 temp = 0; RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); PWR_BackupAccessCmd(ENABLE); /* Is it the first configuration */ BKP_DeInit(); RCC_LSEConfig(RCC_LSE_ON); while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET && temp < 250) { temp++; Delay_Ms(20); } if(temp >= 250) return 1; RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); RCC_RTCCLKCmd(ENABLE); RTC_WaitForLastTask(); RTC_WaitForSynchro(); // RTC_ITConfig(RTC_IT_ALR, ENABLE); RTC_ITConfig(RTC_IT_SEC, ENABLE); RTC_WaitForLastTask(); RTC_EnterConfigMode(); RTC_SetPrescaler(32767); RTC_WaitForLastTask(); RTC_Set(2019, 10, 8, 13, 58, 55); /* Setup Time */ RTC_ExitConfigMode(); BKP_WriteBackupRegister(BKP_DR1, 0XA1A1); RTC_NVIC_Config(); RTC_Get(); return 0; } /********************************************************************* * @fn Is_Leap_Year * * @brief Judging whether it is a leap year. * * @param year * * @return 1 - Yes * 0 - No */ u8 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 */ u8 RTC_Set(u16 syear, u8 smon, u8 sday, u8 hour, u8 min, u8 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 */ u8 RTC_Alarm_Set(u16 syear, u8 smon, u8 sday, u8 hour, u8 min, u8 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 * * @brief Get current time. * * @return 1 - error * 0 - success */ u8 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 { temp1++; 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_Get_Week * * @brief Get the current day of the week. * * @param year/month/day * * @return week */ u8 RTC_Get_Week(u16 year, u8 month, u8 day) { u16 temp2; u8 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 main * * @brief Main program. * * @return none */ int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init(115200); printf("SystemClk:%d\r\n", SystemCoreClock); printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() ); printf("RTC Test\r\n"); RTC_Init(); while(1) { Delay_Ms(1000); printf("year/month/day/week/hour/min/sec:\r\n"); printf("%d-%d-%d %d %d:%d:%d\r\n", calendar.w_year, calendar.w_month, calendar.w_date, calendar.week, calendar.hour, calendar.min, calendar.sec); } }