OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4728|回复: 6

GD32F4系列,RTC闹钟如何设置成每天固定时间起作用?

[复制链接]

53

主题

167

帖子

0

精华

高级会员

Rank: 4

积分
840
金钱
840
注册时间
2016-8-23
在线时间
116 小时
发表于 2022-1-19 17:21:42 | 显示全部楼层 |阅读模式
10金钱
本帖最后由 紫气东升 于 2022-1-19 17:24 编辑

目前配置的只能是当天的闹钟,如何做到每天在设置的那个时间点进闹钟呢?哪位大佬帮忙解答下。GD32跟STM32不太一样,没法参照。以下是我做的闹钟代码,该如何修改成每天的闹钟。用的是库函数提供的寄存器操作方法。
void rtc_pre_config(void)
{
    /* enable access to RTC registers in backup domain */
    rcu_periph_clock_enable(RCU_PMU);
    pmu_backup_write_enable();

#if defined (RTC_CLOCK_SOURCE_IRC32K)
    rcu_osci_on(RCU_IRC32K);
    while(ERROR == rcu_osci_stab_wait(RCU_IRC32K));
    rcu_rtc_clock_config(RCU_RTCSRC_IRC32K);
    prescaler_a = 0x63;  //ck_apre频率 = RTC_CLOCK/(prescaler_a+1) = 32000/(99+1)=320HZ
    prescaler_s = 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_s = 0xFF;
    prescaler_a = 0x7F;
    #else
    #error RTC clock source should be defined
#endif
    rcu_periph_clock_enable(RCU_RTC);
    rtc_register_sync_wait();
}


void rtc_setup(uint8_t *rtc_buf)
{
    /* setup RTC time value */
    uint32_t tmp_hh = 0xFF;
    uint32_t tmp_mm = 0xFF;
    uint32_t tmp_ss = 0xFF;
    uint8_t year_data = 0;
    uint8_t date_data = 0;
    uint8_t alarm_date_data = 0;

    rtc_initpara.factor_asyn = prescaler_a;
    rtc_initpara.factor_syn = prescaler_s;
    year_data = HEXtoBCD(rtc_buf[6]);
    rtc_initpara.year = year_data;

    switch(rtc_buf[7])
    {
        case 0x01:
            rtc_initpara.month = RTC_JAN;
            break;
        case 0x02:
            rtc_initpara.month = RTC_FEB;
            break;
        case 0x03:
            rtc_initpara.month = RTC_MAR;
            break;
        case 0x04:
            rtc_initpara.month = RTC_APR;
            break;
        case 0x05:
            rtc_initpara.month = RTC_MAY;
            break;
        case 0x06:
            rtc_initpara.month = RTC_JUN;
            break;
        case 0x07:
            rtc_initpara.month = RTC_JUL;
            break;
        case 0x08:
            rtc_initpara.month = RTC_AUG;
            break;
        case 0x09:
            rtc_initpara.month = RTC_SEP;
            break;
        case 0x0A:
            rtc_initpara.month = RTC_OCT;
            break;
        case 0x0B:
            rtc_initpara.month = RTC_NOV;
            break;
        case 0x0C:
            rtc_initpara.month = RTC_DEC;
            break;
        default:
            break;
    }
    date_data = HEXtoBCD(rtc_buf[8]);
    rtc_initpara.date = date_data;
    switch(rtc_buf[9])
    {
        case 0x01:
            rtc_initpara.day_of_week = RTC_MONDAY;
            break;
        case 0x02:
            rtc_initpara.day_of_week = RTC_TUESDAY;
            break;
        case 0x03:
            rtc_initpara.day_of_week = RTC_WEDSDAY;
            break;
        case 0x04:
            rtc_initpara.day_of_week = RTC_THURSDAY;
            break;
        case 0x05:
            rtc_initpara.day_of_week = RTC_FRIDAY;
            break;
        case 0x06:
            rtc_initpara.day_of_week = RTC_SATURDAY;
            break;
        case 0x07:
            rtc_initpara.day_of_week = RTC_SUNDAY;
            break;
        default:
            break;
    }
    if(rtc_buf[10] == 0x00)
    {
        rtc_initpara.display_format = RTC_12HOUR;
    }
    else if(rtc_buf[10] == 0x01)
    {
        rtc_initpara.display_format = RTC_24HOUR;
    }
    if(rtc_buf[11] == 0x00)
    {
        rtc_initpara.am_pm = RTC_AM;
    }
    else if(rtc_buf[11] == 0x01)
    {
        rtc_initpara.am_pm = RTC_PM;
    }
    /* 输入当前时间 */
    while(tmp_hh == 0xFF)
    {
        if(rtc_initpara.display_format == RTC_24HOUR)
        {
            tmp_hh = usart_input_threshold(rtc_buf[12], 23);
        }
        else
        {
            tmp_hh = usart_input_threshold(rtc_buf[12], 12);
        }
        rtc_initpara.hour = tmp_hh;
    }

    while(tmp_mm == 0xFF)
    {
        tmp_mm = usart_input_threshold(rtc_buf[13], 59);
        rtc_initpara.minute = tmp_mm;
    }
    while(tmp_ss == 0xFF)
    {
        tmp_ss = usart_input_threshold(rtc_buf[14], 59);
        rtc_initpara.second = tmp_ss;
    }

    /* RTC current time configuration */
    if(ERROR == rtc_init(&rtc_initpara))
    {
        printf("\r\n** RTC time configuration failed! **\r\n");
    }
    else
    {
        printf("\r\n** RTC time configuration success! **\r\n");
    }

    /* setup RTC alarm */
    tmp_hh = 0xFF;
    tmp_mm = 0xFF;
    tmp_ss = 0xFF;

    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;
    alarm_date_data = HEXtoBCD(rtc_buf[15]);
    rtc_alarm.alarm_day = alarm_date_data;
    if(rtc_buf[16] == 0x00)
    {
        rtc_alarm.am_pm = RTC_AM;
    }
    else if(rtc_buf[16] == 0x01)
    {
        rtc_alarm.am_pm = RTC_PM;
    }
    /* RTC alarm input */
    while(tmp_hh == 0xFF)
    {
        if(rtc_initpara.display_format == RTC_24HOUR)
        {
            tmp_hh = usart_input_threshold(rtc_buf[17], 23);
        }
        else
        {
            tmp_hh = usart_input_threshold(rtc_buf[17], 12);
        }
        rtc_alarm.alarm_hour = tmp_hh;
    }

    while(tmp_mm == 0xFF)
    {
        tmp_mm = usart_input_threshold(rtc_buf[18], 59);
        rtc_alarm.alarm_minute = tmp_mm;
    }
    while(tmp_ss == 0xFF)
    {
        tmp_ss = usart_input_threshold(rtc_buf[19], 59);
        rtc_alarm.alarm_second = tmp_ss;
    }

    rtc_flag_clear(RTC_STAT_ALRM0F);
    exti_flag_clear(EXTI_17);

    /* RTC alarm configuration */
    rtc_alarm_config(RTC_ALARM0, &rtc_alarm);
    nvic_irq_enable(RTC_Alarm_IRQn, 3, 0);
    rtc_alarm_enable(RTC_ALARM0);

    /* RTC alarm interrupt configuration */
    exti_init(EXTI_17,EXTI_INTERRUPT, EXTI_TRIG_RISING);
    rtc_interrupt_enable(RTC_INT_ALARM0);
}

uint8_t usart_input_threshold(uint8_t buffer, uint32_t value)
{
    uint32_t index = 0;
    uint32_t bcd_data = 0;

    bcd_data = HEXtoBCD(buffer);
    index = (bcd_data & 0x0F) + ((bcd_data >> 4) * 10);
    if (index > value)
    {
        printf("\r\n please input a valid number between 0 and %d \r\n", value);
        return 0xFF;
    }
    return bcd_data;
}


unsigned int HEXtoBCD(unsigned char hex_data)
{
    unsigned int bcd_data = 0;
    unsigned char temp = 0;

    temp = hex_data % 100;
    bcd_data = ((unsigned int)hex_data) / 100 << 8;
    bcd_data = bcd_data | ((temp / 10) << 4);
    bcd_data = bcd_data | (temp % 10);
    return bcd_data;
}void RTC_Alarm_IRQHandler(void)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    if(RESET != rtc_flag_get(RTC_STAT_ALRM0F))
    {
        rtc_flag_clear(RTC_STAT_ALRM0F);
        exti_flag_clear(EXTI_17);
        rtc_alarm_disable(RTC_ALARM0);
        led_toggle(LED1);
    }
}



最佳答案

查看完整内容[请看2#楼]

很简单的问题 你在闹铃后重新设置下一次闹铃在第二天的同一时间即可。
天道酬勤
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2022-1-19 17:21:43 | 显示全部楼层
很简单的问题
你在闹铃后重新设置下一次闹铃在第二天的同一时间即可。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

53

主题

167

帖子

0

精华

高级会员

Rank: 4

积分
840
金钱
840
注册时间
2016-8-23
在线时间
116 小时
 楼主| 发表于 2022-1-20 08:49:52 | 显示全部楼层
正点原子 发表于 2022-1-20 01:58
很简单的问题
你在闹铃后重新设置下一次闹铃在第二天的同一时间即可。

额额,这也是一种办法。要是能有只设置一次搞定的办法就更好了
天道酬勤
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2022-1-21 01:37:28 | 显示全部楼层
紫气东升 发表于 2022-1-20 08:49
额额,这也是一种办法。要是能有只设置一次搞定的办法就更好了

没有
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

13

主题

643

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2432
金钱
2432
注册时间
2019-12-28
在线时间
527 小时
发表于 2022-1-24 13:58:05 | 显示全部楼层
你程序里面配置,让程序去配就好啦
回复

使用道具 举报

53

主题

167

帖子

0

精华

高级会员

Rank: 4

积分
840
金钱
840
注册时间
2016-8-23
在线时间
116 小时
 楼主| 发表于 2022-1-25 09:05:41 | 显示全部楼层
是的。我将rtc_setup()这个函数里的配置闹钟部分代码摘除出来单独作为一个闹钟函数。第一次进闹钟中断后,在重新执行一遍闹钟函数。
不过,现在又发现了另外一个严重的问题,就是void rtc_pre_config(void)函数(使用内部32K晶振)里异步分频、同步分频配置不对,导致读出来的实时时钟跟实际的时钟不相符,比实际时间要慢。大概一两分钟就慢了10s,这样慢慢积累,一天下来时间偏差就非常大了。有谁知道prescaler_a,prescaler_s这两个分频该怎么配置才能让时间精准?
天道酬勤
回复

使用道具 举报

53

主题

167

帖子

0

精华

高级会员

Rank: 4

积分
840
金钱
840
注册时间
2016-8-23
在线时间
116 小时
 楼主| 发表于 2022-1-25 09:06:02 | 显示全部楼层
狼里个狼121 发表于 2022-1-24 13:58
你程序里面配置,让程序去配就好啦

说的对
天道酬勤
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-8 10:29

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表