打印

GD32F407V RTC实时时间有时不走动

[复制链接]
902|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jacksonjim|  楼主 | 2022-5-18 09:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 jacksonjim 于 2022-5-18 13:40 编辑

目前有个项目上使用RTC,一开始验证RTC时间是正常,使用外部LXATL晶振,后面整合到系统后,在做IAP升级操作时,没有进行全部擦除,只升级应用部分程序,目前出现问题是RTC 在内部有电池供电情况下,断了其它电源输入后时间会出现停止不走动或会遇到出现类似重置RTC 备份域的归零时间了,硬件上排查没有发现问题点,目前想知道有哪些初始化的关键点,是否引起这些问题!RTC初始化参考了GD官方的demo和其它几个示例进行修改,
另外 目前GD32好像没有找到关于时间同步校正设置时间的函数,因为在日常使用中必须通过上位机来修改时间,如果每次都要走RTC重置来达到好像也不太合理,因为在正常量产时不可能每次下载软件能达到同步的,这也是不太合理的,STM32是有HAL库函数可以直接修改时间的,所以不明白GD32的为什么没有想到这点的,是因为GD32的RTC本身就是一个**肋的功能还是其它原因呢不是很明白?目前个人研究尝试用实现函数rtc_time_update来达到修改同步时间,但是好像是不太行,目前不知道具体原因是什么?


麻烦各位大神帮看下分析分析原因。谢谢


RTC 主要代码逻辑部分

rtc_timestamp_struct rtc_timestamp;
rtc_tamper_struct rtc_tamper;
rtc_parameter_struct rtc_initpara;
__IO uint32_t prescaler_a = 0, prescaler_s = 0;

void rtc_pre_config(void);

void RTC_init(void)
{
#if 0
    nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);

    rcu_periph_clock_enable(RCU_GPIOC);
    rcu_periph_clock_enable(RCU_SYSCFG);
    gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_13);
#endif
    // enable access to RTC registers in backup domain
    rcu_periph_clock_enable(RCU_PMU);
    pmu_backup_write_enable();

    rtc_pre_config();

    // rtc_tamper_disable(RTC_TAMPER0);

    /* check if RTC has aready been configured */
    if (BKP_VALUE != RTC_BKP0)
    {
        rtc_time_set(0x22, RTC_MAY, 0x17, 0x00, 0x00, 0x00);
    }
    else
    {
        /* detect the reset source */
        if (RESET != rcu_flag_get(RCU_FLAG_PORRST))
        {
            // printf("power on reset occurred....\n\r");
        }
        else if (RESET != rcu_flag_get(RCU_FLAG_EPRST))
        {
            // printf("external reset occurred....\n\r");
        }
        // printf("no need to configure RTC....\n\r");

        // rtc_show_time();
    }

    rcu_all_reset_flag_clear();
#if 0
    exti_flag_clear(EXTI_21);
    exti_init(EXTI_21, EXTI_INTERRUPT, EXTI_TRIG_RISING);
    nvic_irq_enable(TAMPER_STAMP_IRQn, 0, 0);


    /* RTC tamper configuration */
    rtc_tamper.tamper_filter = RTC_FLT_EDGE;
    rtc_tamper.tamper_source = RTC_TAMPER0;
    rtc_tamper.tamper_trigger = RTC_TAMPER_TRIGGER_EDGE_FALLING;
    rtc_tamper.tamper_with_timestamp = ENABLE;
    rtc_tamper_enable(&rtc_tamper);

    rtc_interrupt_enable(RTC_INT_TAMP);
    rtc_flag_clear(RTC_FLAG_TS | RTC_FLAG_TSOVR | RTC_FLAG_TP0);
    /* rtc_timestamp_enable(RTC_TIMESTAMP_FALLING_EDGE);
    rtc_interrupt_enable(RTC_INT_TIMESTAMP);
    rtc_flag_clear(RTC_FLAG_TS | RTC_FLAG_TSOVR); */
#endif
}

void rtc_pre_config(void)
{
#if defined(RTC_CLOCK_SOURCE_IRC32K)
    rcu_osci_on(RCU_IRC32K);
    rcu_osci_stab_wait(RCU_IRC32K);
    rcu_rtc_clock_config(RCU_RTCSRC_IRC32K);

    prescaler_a = 0x63;  // 0x63  ck_apre频率 = RTC_CLOCK / (prescaler_a+1) = 32000 / (99+1)=320HZ
    prescaler_s = 0x118; // 0x13F ck_spre频率 = ck_apre / (prescaler_s+1) = 320 / (319+1)=1HZ
#elif defined(RTC_CLOCK_SOURCE_LXTAL)
    rcu_osci_on(RCU_LXTAL);
    rcu_osci_stab_wait(RCU_LXTAL);
    rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);

    prescaler_a = 0x7F; // ck_apre频率 = RTC_CLOCK/(prescaler_a+1) = 32768/(127+1)=256HZ
    prescaler_s = 0xFF; // ck_spre频率 = ck_apre/(prescaler_s+1) = 256/(255+1)=1HZ
#else
#error RTC clock source should be defined.
#endif /* RTC_CLOCK_SOURCE_IRC32K */

    // rtc_smooth_calibration_config(RTC_CALIBRATION_WINDOW_32S, RTC_CALIBRATION_PLUS_SET, 0x1F);
    // rtc_coarse_calibration_config(CALIB_INCREASE, 0x1F);

    // rtc_coarse_calibration_config(CALIB_DECREASE, 0x1D); //对晶振进行粗校准
    rcu_periph_clock_enable(RCU_RTC);
    rtc_register_sync_wait();
}

ErrStatus rtc_time_set(uint16_t year, uint8_t month, uint8_t day, uint8_t hh, uint8_t mm, uint8_t ss)
{
    rtc_initpara.factor_asyn = prescaler_a;
    rtc_initpara.factor_syn = prescaler_s;
    rtc_initpara.year = year & 0x00FF;
    rtc_initpara.day_of_week = RTC_SATURDAY;
    rtc_initpara.month = month;
    rtc_initpara.date = day;
    rtc_initpara.display_format = RTC_24HOUR;
    rtc_initpara.am_pm = RTC_AM;

    // current time input
    // =======Configure RTC Time========
    rtc_initpara.hour = hh;
    rtc_initpara.minute = mm;
    rtc_initpara.second = ss;

    /* RTC current time configuration */
    if (ERROR == rtc_init(&rtc_initpara))
    {
        return ERROR;
    }
    else
    {
        RTC_BKP0 = BKP_VALUE;
        return SUCCESS;
    }
}

ErrStatus rtc_time_update(uint16_t year, uint8_t month, uint8_t day, uint8_t hh, uint8_t mm, uint8_t ss)
{
    uint32_t reg_time = 0U, reg_date = 0U;
    ErrStatus error_status = ERROR;
    reg_date = (DATE_YR(year) |
                DATE_DOW(RTC_SATURDAY) |
                DATE_MON(month) |
                DATE_DAY(day));

    reg_time = (RTC_AM |
                TIME_HR(hh) |
                TIME_MN(mm) |
                TIME_SC(ss));

    /* 1st: disable the write protection */
    RTC_WPK = RTC_UNLOCK_KEY1;
    RTC_WPK = RTC_UNLOCK_KEY2;
    error_status = rtc_init_mode_enter();
    if (ERROR != error_status)
    {
        RTC_TIME = (uint32_t)reg_time;
        RTC_DATE = (uint32_t)reg_date;
        rtc_init_mode_exit();
        error_status = rtc_register_sync_wait();
    }
    RTC_WPK = RTC_LOCK_KEY;
    return error_status;
}

void rtc_alart_set(uint8_t hh, uint8_t mm, uint8_t ss)
{
    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 = 0x31;
    rtc_alarm.am_pm = RTC_AM;

    rtc_alarm.alarm_hour = hh;

    rtc_alarm.alarm_minute = mm;

    rtc_alarm.alarm_second = ss;

    rtc_alarm_config(RTC_ALARM0, &rtc_alarm);

    rtc_alarm_enable(RTC_ALARM0);
}

/**
* [url=home.php?mod=space&uid=247401]@brief[/url] timestamp time
*
*/
void rtc_show_timestamp(void)
{
    char buf[128] = {0};
    uint32_t ts_subsecond = 0;
    uint8_t ts_subsecond_ss, ts_subsecond_ts, ts_subsecond_hs;

    rtc_timestamp_get(&rtc_timestamp);
    /* get the subsecond value of timestamp time, and convert it into fractional format */
    ts_subsecond = rtc_timestamp_subsecond_get();
    ts_subsecond_ss = (1000 - (ts_subsecond * 1000 + 1000) / 400) / 100;
    ts_subsecond_ts = (1000 - (ts_subsecond * 1000 + 1000) / 400) % 100 / 10;
    ts_subsecond_hs = (1000 - (ts_subsecond * 1000 + 1000) / 400) % 10;

    sprintf(buf, "timestamp: %0.2x:%0.2x:%0.2x.%d%d%d \n\r",
            rtc_timestamp.timestamp_hour, rtc_timestamp.timestamp_minute, rtc_timestamp.timestamp_second,
            ts_subsecond_ss, ts_subsecond_ts, ts_subsecond_hs);
    RS485_sendData(UART4, (uint8_t *)buf, strlen(buf));
}

/**
* [url=home.php?mod=space&uid=247401]@brief[/url] current time
*
*/
void rtc_show_time(void)
{
    uint32_t time_subsecond = 0;
    char buf[128] = {0};
    uint8_t subsecond_ss = 0, subsecond_ts = 0, subsecond_hs = 0;

    rtc_current_time_get(&rtc_initpara);

    /* get the subsecond value of current time, and convert it into fractional format */
    time_subsecond = rtc_subsecond_get();
    subsecond_ss = (1000 - (time_subsecond * 1000 + 1000) / 400) / 100;
    subsecond_ts = (1000 - (time_subsecond * 1000 + 1000) / 400) % 100 / 10;
    subsecond_hs = (1000 - (time_subsecond * 1000 + 1000) / 400) % 10;

    sprintf(buf, "CurTime: %0.2x:%0.2x:%0.2x.%d%d%d \n\r",
            rtc_initpara.hour, rtc_initpara.minute, rtc_initpara.second,
            subsecond_ss, subsecond_ts, subsecond_hs);
    RS485_sendData(UART4, (uint8_t *)buf, strlen(buf));
    Uart5_Send_Data((uint8_t *)buf, strlen(buf));
}

void RTC_WKUP_IRQHandler(void)
{
    if (RESET != rtc_flag_get(RTC_FLAG_WT))
    {
        exti_flag_clear(EXTI_22);
        // gd_eval_led_toggle(LED1);
        // rtc_show_time();
        rtc_flag_clear(RTC_FLAG_WT);
    }
}

/*!
    \brief      this function handles RTC interrupt request
    \param[in]  none
    \param[out] none
    \retval     none
*/
void RTC_Alarm_IRQHandler(void)
{
    if (RESET != rtc_flag_get(RTC_FLAG_ALRM0))
    {
        rtc_flag_clear(RTC_FLAG_ALRM0);
        exti_flag_clear(EXTI_17);
        // gd_eval_led_toggle(LED2);
    }
}

/*!
    \brief      this function handles RTC interrupt request
    \param[in]  none
    \param[out] none
    \retval     none
*/
void TAMPER_STAMP_IRQHandler(void)
{
    if (RESET != rtc_flag_get(RTC_FLAG_TP0))
    // if (RESET != rtc_flag_get(RTC_FLAG_TS))
    {
        exti_flag_clear(EXTI_21);
        // gd_eval_led_toggle(LED1);

        /* if tamper0 event occurs, check if the BKP0 register has been reset or not */
        /*  if(BKP_VALUE != RTC_BKP0)
             gd_eval_led_toggle(LED2);
         else
             gd_eval_led_toggle(LED3); */

        rtc_show_timestamp();
        rtc_flag_clear(RTC_FLAG_TS | RTC_FLAG_TSOVR | RTC_FLAG_TP0);

        // rtc_flag_clear(RTC_FLAG_TS | RTC_FLAG_TSOVR);
    }
}



使用特权

评论回复
沙发
caizhiwei| | 2023-3-20 13:38 | 只看该作者
留个记号

使用特权

评论回复
板凳
caizhiwei| | 2023-3-24 10:03 | 只看该作者
走不动倒是没遇到过,遇到了奇葩读日期出问题,哎。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

4

帖子

0

粉丝