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

}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值