GD32L233 RTC sleep wake-up and alarm clock wake-up with source code

GD32L233 RTC sleep wake-up and alarm clock wake-up

    • Clock source and frequency division
  • RCT initialization
  • Writing RCT interrupt function
  • BCD to BYTE conversion
  • RTC time judgment

Clock source and frequency division

Using internal clock IRC32K
Average frequency: 31.7-32.3khz
Operating current: 160nA
Wake-up time: 40us
RTC provides a certain time, which includes hours/minutes/seconds/subseconds, and a calendar, which includes day of the year/month/day/week. Except for sub-seconds, time and calendar are expressed in BCD code. Subseconds are expressed in binary code. Adjust time for daylight saving time. Working in power saving mode and smart wake-up are software configurable. Supports the use of an external precision low-frequency clock to improve calendar accuracy.
GD32 divides the RTC into two parts. The core part (prescaler, divider, counter, alarm clock) is placed in backup to achieve the purpose of reset and restart without losing time. The other part (APB1 interface) is placed in the VDD power domain.
Add a battery. When VDD is powered off, it will automatically switch to battery power supply (VBAT) to achieve the purpose of not losing time when the MCU is powered off.
The RTC unit has three independent clock sources: LXTAL, IRC32K and HXTAL
There are 2 frequency dividers, a 7-bit asynchronous frequency divider and the other is a 15-bit synchronous frequency divider. The asynchronous frequency divider is mainly used to reduce energy consumption.

F

=

F

C

/

F

A

C

T

O

R

A

+

1

F = F_C/FACTOR_A + 1

F=FC?/FACTORA? + 1
1HZ automatic wake-up calculation 32K/128/250 = 1HZ
7-bit asynchronous divider = 128
15-bit sync divider = 250
Automatic wake-up is mounted to EXTI_20, priority 2, alarm clock Alarm is mounted to EXTI_17, priority 0

RCT initialization

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( & amp;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, & amp;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);
}

Writing RCT interrupt function

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 to BYTE conversion

static uint8_t RTC_Bcd2ToByte(uint8_t Value)
{<!-- -->
    uint8_t tmp;
    tmp = ((Value & amp; 0xF0u) >> 4u) * 10u;
    return (tmp + (Value & amp; 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 time judgment

Determine whether 96 hours has been reached and switch modes.

uint8_t RTC_Reach_96hours(void)
{<!-- -->
    rtc_current_time_get( & amp;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 96 hours 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 & amp; & amp;
             rtc_now_time.hour - rtc_last_time.hour >= 0 & amp; & amp;
             rtc_now_time.minute - rtc_last_time.minute >= 0))
    {<!-- -->
        printf("reach 96hours");
        return 1;
    }
    return 0;
}
void RTC_Refresh_last_time(void)
{<!-- -->
    rtc_current_time_get( & amp;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);

}