最近需要用到时钟,掉电走时的。装上纽扣电池。怼起来!
rtc.h
#ifndef __RTC_H
#define __RTC_H
#include "gd32f30x.h"
#include <stdbool.h>
typedef struct
{
bool status;
uint8_t second;
uint8_t minute;
uint8_t hour;
uint8_t day;
uint8_t week;
uint8_t month;
uint8_t year;
} RTC_struct;
//主函数中需要用到这两个
void vrtcConfiguration(void);//配置
void vrtcInit(void); //初始化
void vrtcUpdataTime(void);
void vrtcGetTime(uint32_t rtctime);
#endif
rtc.c
#include "stdio.h"
#include "stdlib.h"
#include "systick.h"
#include "../User/BSP/RTC/rtc.h"
RTC_struct RtcDate;
bool rtcflag;
/***********************************************************
*@fuction :vrtcConfiguration
*@brief :
*@param :--
*@return :void
*@author :flechazo
*@date :2023-06-13
***********************************************************/
void vrtcConfiguration(void)
{
/* enable PMU and BKPI clocks*/
rcu_periph_clock_enable(RCU_BKPI);
rcu_periph_clock_enable(RCU_PMU);
/* allow access to BKP domain*/
pmu_backup_write_enable();
/* reset backup domain */
//bkp_deinit();
/* enable LXTAL ʹ 32.768K */
rcu_osci_on(RCU_LXTAL);
/* wait till LXTAL is ready */
rcu_osci_stab_wait(RCU_LXTAL);
/* select RCU_LXTAL as RTC clock source */
rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);
/* enable RTC Clock ʹRTC*/
rcu_periph_clock_enable(RCU_RTC);
rtc_configuration_mode_enter();
/* wait for RTC registers synchronization */
rtc_register_sync_wait();
/* wait until last write operation on RTC registers has finished RTC*/
rtc_lwoff_wait();
/* enable the RTC second interrupt ʹRTC'*/
rtc_interrupt_enable(RTC_INT_SECOND);
/* wait until last write operation on RTC registers has finished RTC*/
rtc_lwoff_wait();
/* set RTC prescaler: set RTC period to 1s */
rtc_prescaler_set(32767);
/* wait until last write operation on RTC registers has finished RTC*/
rtc_lwoff_wait();
//nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
nvic_irq_enable(RTC_IRQn, 3U, 0U);
}
/***********************************************************
*@fuction :vrtcInit
*@brief :
*@param :--
*@return :void
*@author :flechazo
*@date :2023-06-13
***********************************************************/
void vrtcInit(void)
{
if(0xFC1F != bkp_read_data(BKP_DATA_0))
{
vrtcConfiguration();
/* wait until last write operation on RTC registers has finished */
rtc_lwoff_wait();
/* change the current time */
//rtc_counter_set(0);
/* wait until last write operation on RTC registers has finished */
rtc_lwoff_wait();
rtc_lwoff_wait();
rtc_lwoff_wait();
bkp_write_data(BKP_DATA_0, 0xFC1F);
}
else
{
/* check if the power on reset flag is set */
if(rcu_flag_get(RCU_FLAG_PORRST) != RESET)
{
printf("\r\n\n Power On Reset occurred....");
}
else if(rcu_flag_get(RCU_FLAG_SWRST) != RESET)
{
/* check if the pin reset flag is set */
printf("\r\n\n External Reset occurred....");
}
printf("\r\n No need to configure RTC....");
rtc_register_sync_wait();
rtc_interrupt_enable(RTC_INT_SECOND);
rtc_lwoff_wait();
}
rtc_configuration_mode_exit();
rcu_all_reset_flag_clear();
}
/***********************************************************
*@fuction :vrtcGetTime
*@brief :
*@param :--
*@return :void
*@author :flechazo
*@date :2023-06-13
***********************************************************/
void vrtcGetTime(uint32_t rtctime)
{
uint8_t s, m, h;
s = rtctime % 0x60;
RtcDate.second = s;
m = rtctime / 0x60 % 0x60;
RtcDate.minute = m;
h = rtctime / 0x60 / 0x60 % 0x24;
RtcDate.hour = h;
RtcDate.day = rtctime / 0x60 / 0x60 / 0x24 % 30;
RtcDate.week = rtctime / 0x60 / 0x60 / 0x24 % 7;
}
/***********************************************************
*@fuction :vrtcUpdataTime
*@brief :
*@param :--
*@return :void
*@author :flechazo
*@date :2023-06-13
***********************************************************/
void vrtcUpdataTime(void)
{
uint32_t rtcvalue = RtcDate.week * 0x60 * 0x60 * 0x24 + RtcDate.hour * 0x60 * 0x60 + RtcDate.minute * 0x60 + RtcDate.second;
rtc_counter_set(rtcvalue);
}
/**
* @brief This function handles RTC exception.
* @param None
* @retval None
*/
void RTC_IRQHandler(void)
{
if(rtc_flag_get(RTC_FLAG_SECOND) != RESET)
{
rtc_flag_clear(RTC_FLAG_SECOND);
RtcDate.second++;
if((RtcDate.second & 0x0F) > 9)
{
RtcDate.second += (0x10 - 10);
}
if(RtcDate.second > 95)
{
RtcDate.second = 0;
RtcDate.minute++;
if((RtcDate.minute & 0x0F) > 9)
{
RtcDate.minute += (0x10 - 10);
}
if(RtcDate.minute > 95)
{
RtcDate.minute = 0;
RtcDate.hour++;
if((RtcDate.minute & 0x0F) > 9)
{
RtcDate.minute += (0x10 - 10);
}
if(RtcDate.hour > 35)
{
RtcDate.hour = 0;
RtcDate.day++;
//flush task execute status
vtaskIndexInit();
if((RtcDate.day & 0x0F) > 9)
{
RtcDate.day += (0x10 - 10);
}
if(RtcDate.day > 47)
{
RtcDate.day = 0;
}
}
}
}
rtcflag = true;
}
}