问答

汇集网友智慧,解决技术难题

21ic问答首页 - GD32L233 怎么通过RTC实现秒中断

RTC gd32l233

GD32L233 怎么通过RTC实现秒中断

fxliuqq2025-06-21
GD32L233 怎么通过RTC实现秒中断
回答 +关注 1
391人浏览 1人回答问题 分享 举报
1 个回答
  • #include "gd32l23x.h"
    #include <stdio.h>

    // 时间结构体定义
    typedef struct {
        uint8_t seconds;
        uint8_t minutes;
        uint8_t hours;
        uint8_t day;
        uint8_t date;
        uint8_t month;
        uint16_t year;
    } rtc_time;

    volatile uint32_t seconds_counter = 0;  // 秒计数器
    volatile uint8_t time_updated = 0;      // 时间更新标志

    // 时间初始化值
    rtc_time initial_time = {
        .seconds = 0,
        .minutes = 0,
        .hours = 12,
        .day = 1,     // 周一
        .date = 1,    // 1号
        .month = 1,   // 1月
        .year = 2024  // 2024年
    };

    // RTC初始化函数
    void rtc_configuration(void)
    {
        /* 1. 使能时钟 */
        rcu_periph_clock_enable(RCU_PMU);
        rcu_periph_clock_enable(RCU_BDCU);

        /* 2. 使能备份域写访问 */
        pmu_backup_write_enable();

        /* 3. 配置RTC时钟源为LXTAL */
        rcu_osci_on(RCU_LXTAL);
        rcu_osci_stab_wait(RCU_LXTAL);
        rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);

        /* 4. 使能RTC时钟 */
        rcu_periph_clock_enable(RCU_RTC);

        /* 5. 等待RTC寄存器同步 */
        rtc_register_sync_wait();

        /* 6. 配置预分频器 */
        // 异步分频器:127 (32768/(127+1)=256Hz)
        // 同步分频器:255 (256/(255+1)=1Hz)
        rtc_prescaler_config(127, 255);

        /* 7. 配置秒中断 */
        rtc_interrupt_enable(RTC_INT_SECOND);

        /* 8. 等待配置完成 */
        rtc_lwoff_wait();

        /* 9. 初始化时间 */
        rtc_time_set(&initial_time);

        /* 10. 使能NVIC中断 */
        nvic_irq_enable(RTC_IRQn, 0, 0);
    }

    // 设置时间
    void rtc_time_set(rtc_time *time)
    {
        /* 等待寄存器可写 */
        rtc_lwoff_wait();

        /* 设置时间 */
        rtc_counter_set(
            (uint32_t)time->seconds +
            (uint32_t)time->minutes * 60 +
            (uint32_t)time->hours * 3600
        );

        /* 设置日期 */
        rtc_date_set(
            time->year,
            time->month,
            time->date,
            time->day
        );
    }

    // 获取时间
    void rtc_time_get(rtc_time *time)
    {
        uint32_t counter = rtc_counter_get();
        rtc_date_struct date;
        rtc_current_date_get(&date);

        time->seconds = counter % 60;
        time->minutes = (counter / 60) % 60;
        time->hours = counter / 3600;
        time->day = date.weekday;
        time->date = date.day;
        time->month = date.month;
        time->year = date.year;
    }

    // RTC中断服务函数
    void RTC_IRQHandler(void)
    {
        if(RESET != rtc_flag_get(RTC_FLAG_SECOND)) {
            /* 清除秒中断标志 */
            rtc_flag_clear(RTC_FLAG_SECOND);

            /* 更新秒计数器 */
            seconds_counter++;

            /* 设置时间更新标志 */
            time_updated = 1;
        }
    }

    // 打印当前时间
    void print_current_time(void)
    {
        rtc_time current_time;
        rtc_time_get(&current_time);

        printf("当前时间: %04u-%02u-%02u %02u:%02u:%02u 星期%u\n",
               current_time.year,
               current_time.month,
               current_time.date,
               current_time.hours,
               current_time.minutes,
               current_time.seconds,
               current_time.day);
    }

    int main(void)
    {
        /* 系统时钟配置 */
        rcu_system_clock_config(RCU_CKSYSSRC_HXTAL, RCU_PLL_MUL6, RCU_PLL_DIV1);

        /* 初始化串口 */
        // 这里省略串口初始化代码,实际使用时需要添加

        /* 初始化RTC */
        rtc_configuration();

        printf("GD32L233 RTC秒中断演示\n");
        printf("RTC已初始化,每秒产生一次中断\n");

        while(1) {
            if(time_updated) {
                time_updated = 0;
                print_current_time();
                printf("系统运行秒数: %lu\n", seconds_counter);
            }

            // 主循环中执行其他任务...
        }
    }

您需要登录后才可以回复 登录 | 注册