查看: 2761|回复: 0

GD32F450学习——RTC实验

[复制链接]
  • TA的每日心情
    奋斗
    2023-6-27 14:09
  • 签到天数: 943 天

    连续签到: 1 天

    [LV.10]以坛为家III

    发表于 2017-4-24 09:06:17 | 显示全部楼层 |阅读模式
    分享到:
    液晶屏成功驱动后,首先想到的是做一个闹钟。GD32F450自带RTC模块,详细如下:



           RTC可以计时,也可以设置闹钟,这次没有设定键盘,所以不能调节时间,只能在代码里设置好,并设定一个闹钟,闹钟时间到时,可以出发中断去执行特定操作,这里是让程序点亮LED,如果接蜂鸣器,就是闹铃了。
    下面部分是预设值函数,由于小红板没有外部32K晶振,只能选择内部时钟,所以需要提前声明RTC_CLOCK_SOURCE_IRC32K一下,这样初始化时会使用内部时钟,如果选用外部时钟是无法工作的。

    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_s = 0x13F;
    prescaler_a = 0x63;
    #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 /* RTC_CLOCK_SOURCE_IRC32K */
    rcu_periph_clock_enable(RCU_RTC);
    rtc_register_sync_wait();
    }
    这部分是RTC设置函数,在里面进行了时间和日期的设置,并且设定了闹钟,(此处时间与真实时间不符)。

    void rtc_setup(void)
    {
    /* setup RTC time value */
    uint32_t tmp_hh = 0xFF, tmp_mm = 0xFF, tmp_ss = 0xFF;rtc_initpara.factor_asyn = prescaler_a;
    rtc_initpara.factor_syn = prescaler_s;
    rtc_initpara.year = 0x16;
    rtc_initpara.day_of_week = RTC_SATURDAY;
    rtc_initpara.month = RTC_APR;
    rtc_initpara.date = 0x30;
    rtc_initpara.display_format = RTC_24HOUR;
    rtc_initpara.am_pm = RTC_AM;
    /* setup RTC alarm */
    tmp_hh = 0X19;
    tmp_mm = 0X40;
    tmp_ss = 0X20;
    rtc_initpara.hour = tmp_hh;
    rtc_initpara.minute = tmp_mm;
    rtc_initpara.second = tmp_ss;
    /* RTC current time configuration */
    if(ERROR == rtc_init(&rtc_initpara)){
    //GPIO_BOP(GPIOD) = GPIO_PIN_7;
    Gui_DrawFont_GBK16(30, 40, RED, GRAY0,"failed");
    }else{
    //GPIO_BC(GPIOD) = GPIO_PIN_7;
    Gui_DrawFont_GBK16(30, 40, RED, GRAY0,"ok");
    rtc_show_time();
    RTC_BKP0 = BKP_VALUE;
    }
    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 input */
    tmp_hh = 0x19;
    tmp_mm = 0X41;
    tmp_ss = 0x20;
    rtc_alarm.alarm_hour = tmp_hh;
    rtc_alarm.alarm_minute = tmp_mm;
    rtc_alarm.alarm_second = tmp_ss;
    /* RTC alarm configuration */
    rtc_alarm_config(RTC_ALARM0,&rtc_alarm);
    rtc_show_alarm();
    rtc_interrupt_enable(RTC_INT_ALARM0);
    rtc_alarm_enable(RTC_ALARM0);
    }
    这两个函数是显示闹钟和时间的函数,主要使用了sprintf函数,将得到的数据转换为字符格式送到显示屏上。

    void rtc_show_time(void)
    {
    uint32_t time_subsecond = 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)0/10;
    subsecond_hs=(1000-(time_subsecond*1000+1000)/400);
    sprintf((char *)buf,"%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);
    Gui_DrawFont_GBK16(0, 80, RED, GRAY0, buf);
    }

    void rtc_show_alarm(void)
    {
    rtc_alarm_get(RTC_ALARM0,&rtc_alarm);
    sprintf((char*)buf,"alarm:%0.2x:%0.2x:%0.2x \n\r", rtc_alarm.alarm_hour, rtc_alarm.alarm_minute,\
    rtc_alarm.alarm_second);
    Gui_DrawFont_GBK16(0, 60, RED, GRAY0, buf);
    }
    这一部分是主函数

    int main(void)
    {
    u8 i=0;
    u16 color=0;
    systick_config();
    led_init();
    Lcd_Init(2);
    Lcd_Clear(GRAY0);/* enable PMU clock */
    rcu_periph_clock_enable(RCU_PMU);
    /* enable the access of the RTC registers */
    pmu_backup_write_enable();
    rtc_pre_config();
    if (BKP_VALUE != RTC_BKP0){
    rtc_setup();
    }else{
    if (RESET != rcu_flag_get(RCU_FLAG_PORRST)){
    // Gui_DrawFont_GBK16(30, 40, RED, GRAY0,"power on");
    }else if (RESET != rcu_flag_get(RCU_FLAG_EPRST)){
    // printf("external reset occurred....\n\r");
    }
    // printf("no need to configure RTC....\n\r");
    rtc_flag_clear(RTC_STAT_ALRM0F);
    exti_flag_clear(EXTI_17);
    rtc_show_time();
    rtc_show_alarm();
    }
    rcu_all_reset_flag_clear();
    /* RTC alarm interrupt configuration */
    exti_init(EXTI_17,EXTI_INTERRUPT,EXTI_TRIG_RISING);
    nvic_irq_enable(RTC_Alarm_IRQn,0,0);
    //        Gui_DrawFont_GBK16(30, 40, RED, GRAY0, "eeboard");
    //        Gui_DrawFont_GBK24(20, 60, BLUE, GRAY0, "GD32F450VE");
    //        Gui_DrawFont_GBK24(30, 20, BLUE, GRAY0, "ID:9robot");
    while(1)
    {
    //        Gui_DrawFont_Num32(20, 100, RED, GRAY0, i);
    GPIO_TG(GPIOB) = GPIO_PIN_3;
    delay_1ms(500);
    GPIO_TG(GPIOB) = GPIO_PIN_4;
    i++;
    if(i==10)i=0;
    rtc_show_time();

    }
    }

    这部分是RTC的闹钟中断函数,在该函数里面设置了点灯程序,当中断发生时,点亮由GPIOD下的PIN7引脚控制的LED。经过测试,当时间到达设定的闹钟时,LED可以点亮,即实验成功。

    void RTC_Alarm_IRQHandler(void)
    {
    if(RESET != rtc_flag_get(RTC_STAT_ALRM0F)){
    rtc_flag_clear(RTC_STAT_ALRM0F);
    exti_flag_clear(EXTI_17);
    GPIO_BOP(GPIOD) = GPIO_PIN_7;
    }
    }

    在调试过程中,发现时间总是不能写到寄存器里,每次写入都会出现错误,后来给板子断电后,重新上电,就可以将时间写入寄存器内,这里应该是由于备份寄存器写保护了,还需要去查一下才可以确认
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-4-19 21:08 , Processed in 0.112119 second(s), 17 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.