fxliuqq 发表于 2025-6-21 15:21

GD32L233 怎么通过RTC实现秒中断

GD32L233 怎么通过RTC实现秒中断

hbzjt2011 发表于 2025-6-24 13:18

GD32L233 怎么通过RTC实现秒中断

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

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

classroom 发表于 2025-7-23 17:00

需完成时钟源配置、预分频设置、中断使能及中断服务函数编写等关键步骤

tpgf 发表于 2025-7-26 16:55

RTC模块内置秒标志位,每当计数器递增时自动置位;使能对应中断后,CPU会在每个秒级沿进入中断服务程序

和下土 发表于 2025-7-31 23:59

具体需结合芯片手册的电气特性说明
页: [1]
查看完整版本: GD32L233 怎么通过RTC实现秒中断