GD32L233 RTC休眠唤醒和闹钟唤醒
时钟源和分频
采用内部时钟IRC32K
平均频率: 31.7-32.3khz
工作电流: 160nA
唤醒时间: 40us
RTC提供了一定的时间,其中包括小时/分/秒/次秒,还有一个日历,包括年/月/日/周的一天。除次秒外,时间和日历都用BCD代码表示。次秒级用二进制代码表示。调整夏令时的时间。工作在省电模式和智能唤醒是软件是可配置的。支持使用外部精确低频时钟提高日历准确性。
GD32将RTC分成两部分,把内核部分(预分频器、分频器、计数器、闹钟)放在备份,达到复位重启不丢时间的目的,其它(APB1接口)放在VDD电源域
增加电池,当VDD断电后,自动切换到电池供电(VBAT),达到MCU断电不丢时间的目的
其中RTC单元有三种独立时钟源分别是:LXTAL,IRC32K和HXTAL
有2个分频器,一个7位异步分频器,另一个是一个15位同步分频器,异步分频器主要用于减少能耗,
F
=
F
C
/
F
A
C
T
O
R
A
+
1
F = F_C/FACTOR_A + 1
F=FC/FACTORA+1
1HZ的自动唤醒计算32K/128/250 = 1HZ
7位异步分频器 = 128
15位同步分频器 = 250
自动唤醒挂载到EXTI_20,优先级2,闹钟Alarm挂载到EXTI_17,优先级0
RCT 初始化
void RTC_Init(void)
{
/* enable BKPI clocks */
rcu_periph_clock_enable(RCU_BKP);
/* allow access to BKP domain */
pmu_backup_write_enable();
rcu_periph_clock_enable(RCU_RTC);
/* enable IRC32K */
rcu_osci_on(RCU_IRC32K);
/* wait for IRC32K stabilization flag */
rcu_osci_stab_wait(RCU_IRC32K);
rcu_lxtal_clock_monitor_enable();
/* configure the RTC clock source selection */
rcu_rtc_clock_config(RCU_RTCSRC_IRC32K);
rtc_register_sync_wait();
/* setup RTC time value */
rtc_initpara.factor_asyn = prescaler_a; // 32K/128/250 = 1HZ
rtc_initpara.factor_syn = prescaler_s;
rtc_initpara.year = 0x16;
rtc_initpara.day_of_week = RTC_WEDNESDAY;
rtc_initpara.month = RTC_JAN;
rtc_initpara.date = 0x01;
rtc_initpara.display_format = RTC_24HOUR;
rtc_initpara.am_pm = RTC_AM;
rtc_initpara.hour = 0x09;
rtc_initpara.minute = 0x28;
rtc_initpara.second = 0;
rtc_init(&rtc_initpara);
/* RTC alarm configuration */
rtc_alarm_struct rtc_alarm;
rtc_alarm_disable(RTC_ALARM0);
rtc_alarm.alarm_mask = RTC_ALARM_DATE_MASK | RTC_ALARM_HOUR_MASK | RTC_ALARM_MINUTE_MASK;
rtc_alarm.weekday_or_date = RTC_ALARM_DATE_SELECTED;
rtc_alarm.alarm_day = 0x05; // 96 hour
rtc_alarm.am_pm = RTC_AM;
rtc_alarm.alarm_hour = 0x09;
rtc_alarm.alarm_minute = 0x28;
rtc_alarm.alarm_second = 0x00;
rtc_alarm_config(RTC_ALARM0, &rtc_alarm);
/* EXTI line 17 configuration */
nvic_irq_enable(RTC_Alarm_IRQn, 0);
exti_flag_clear(EXTI_17);
exti_init(EXTI_17, EXTI_INTERRUPT, EXTI_TRIG_RISING);
rtc_flag_clear(RTC_STAT_ALRM0F);
rtc_interrupt_enable(RTC_INT_ALARM0);
/* EXTI line 20 configuration */
nvic_irq_enable(RTC_WKUP_IRQn, 2);
exti_flag_clear(EXTI_20);
exti_init(EXTI_20, EXTI_INTERRUPT, EXTI_TRIG_RISING);
rtc_flag_clear(RTC_STAT_WTF);
/* wakeup clock configuration */
rtc_wakeup_clock_set(WAKEUP_CKSPRE);
rtc_wakeup_timer_set(1);
rtc_interrupt_enable(RTC_INT_WAKEUP);
/*rtc enable*/
rtc_wakeup_enable();
rtc_alarm_enable(RTC_ALARM0);
// rtc_wakeup_disable();
// rtc_alarm_disable(RTC_ALARM0);
}
RCT中断函数编写
void RTC_WKUP_IRQHandler(void)
{
if(RESET != rtc_flag_get(RTC_FLAG_WT))
{
/* clear EXTI line 20 pending and rtc wakeup flag */
rtc_flag_clear(RTC_FLAG_WT);
exti_flag_clear(EXTI_20);
}
}
void RTC_Alarm_IRQHandler(void)
{
if(RESET != rtc_flag_get(RTC_FLAG_ALARM0))
{
/* clear EXTI line 17 pending and rtc alarm flag */
rtc_flag_clear(RTC_FLAG_ALARM0);
exti_flag_clear(EXTI_17);
}
}
BCD到BYTE的转换
static uint8_t RTC_Bcd2ToByte(uint8_t Value)
{
uint8_t tmp;
tmp = ((Value & 0xF0u) >> 4u) * 10u;
return (tmp + (Value & 0x0Fu));
}
static uint8_t RTC_ByteToBcd2(uint8_t Value)
{
uint32_t bcdhigh = 0u;
uint8_t Param = Value;
while(Param >= 10u)
{
bcdhigh++;
Param -= 10u;
}
return ((uint8_t)(bcdhigh << 4u) | Param);
RTC 时间判断
判断是否到达96小时,进行模式切换
uint8_t RTC_Reach_96hours(void)
{
rtc_current_time_get(&rtc_initpara);
rtc_now_time.year = RTC_Bcd2ToByte(rtc_initpara.year);
rtc_now_time.month = RTC_Bcd2ToByte(rtc_initpara.month);
rtc_now_time.date = RTC_Bcd2ToByte(rtc_initpara.date);
rtc_now_time.hour = RTC_Bcd2ToByte(rtc_initpara.hour);
rtc_now_time.minute = RTC_Bcd2ToByte(rtc_initpara.minute);
rtc_now_time.second = RTC_Bcd2ToByte(rtc_initpara.second);
//check 96hours or not
if((rtc_now_time.year - rtc_last_time.year > 0 || rtc_now_time.month - rtc_last_time.month > 0) ||
(rtc_now_time.date - rtc_last_time.date >= 4 &&
rtc_now_time.hour - rtc_last_time.hour >= 0 &&
rtc_now_time.minute - rtc_last_time.minute >= 0))
{
printf("reach 96hour");
return 1;
}
return 0;
}
void RTC_Refresh_last_time(void)
{
rtc_current_time_get(&rtc_initpara);
rtc_last_time.year = RTC_Bcd2ToByte(rtc_initpara.year);
rtc_last_time.month = RTC_Bcd2ToByte(rtc_initpara.month);
rtc_last_time.date = RTC_Bcd2ToByte(rtc_initpara.date);
rtc_last_time.hour = RTC_Bcd2ToByte(rtc_initpara.hour);
rtc_last_time.minute = RTC_Bcd2ToByte(rtc_initpara.minute);
rtc_last_time.second = RTC_Bcd2ToByte(rtc_initpara.second);
}