[经验分享] 【GD32F350分享】【六】增加RTC时钟功能

hanyeguxingwo   2018-9-21 14:23 楼主
       GD32F350的RTC模块提供了一个包含日期(年/月/日)和时间(时/分/秒/亚秒)的日历功能。除亚秒用二进制码显示外,时间和日期都以BCD码的形式显示。RTC可以进行夏令时补偿。RTC可以工作在省电模式下,并通过软件配置来智能唤醒。RTC支持外接更高精度的低频时钟,用以达到更高的日历精度。
        这里参考库函数里面的例程对RTC进行了初始化和串口时钟设置,实现实时时钟的功能。再工程目录下的Driver文件夹增加rtc源文件和头文件,同时编写RTC初始化函数,再主函数中通过串口进行时分秒设置。这里使用了BKP_VALUE作为时钟是否初始化过的标志位。

  1. void Init_RTC(void)
  2. {
  3.         /* enable PMU clock */
  4.         rcu_periph_clock_enable(RCU_PMU);
  5.         /* enable the access of the RTC registers */
  6.         pmu_backup_write_enable();
  7.        
  8.         rcu_osci_on(RCU_IRC40K);
  9.         rcu_osci_stab_wait(RCU_IRC40K);
  10.         rcu_rtc_clock_config(RCU_RTCSRC_IRC40K);

  11.         prescaler_s = 0x18F;
  12.         prescaler_a = 0x63;
  13.        
  14.         rcu_periph_clock_enable(RCU_RTC);
  15.         rtc_register_sync_wait();
  16. }

  17. /*!
  18.     \brief      use hyperterminal to setup RTC time and alarm
  19.     \param[in]  none
  20.     \param[out] none
  21.     \retval     none
  22. */
  23. void rtc_setup(void)
  24. {
  25.     /* setup RTC time value */
  26.     uint32_t tmp_hh = 0xFF, tmp_mm = 0xFF, tmp_ss = 0xFF;

  27.     rtc_initpara.rtc_factor_asyn = prescaler_a;
  28.     rtc_initpara.rtc_factor_syn = prescaler_s;
  29.     rtc_initpara.rtc_year = 0x18;
  30.     rtc_initpara.rtc_day_of_week = RTC_FRIDAY;
  31.     rtc_initpara.rtc_month = RTC_SEP;
  32.     rtc_initpara.rtc_date = 0x21;
  33.     rtc_initpara.rtc_display_format = RTC_24HOUR;
  34.     rtc_initpara.rtc_am_pm = RTC_AM;

  35.     /* current time input */
  36.     printf("=======Configure RTC Time========\n\r");
  37.     printf("  please input hour:\n\r");
  38.     while (tmp_hh == 0xFF){   
  39.         tmp_hh = usart_input_threshold(23);
  40.         rtc_initpara.rtc_hour = tmp_hh;
  41.     }
  42.     printf("  %0.2x\n\r", tmp_hh);
  43.    
  44.     printf("  please input minute:\n\r");
  45.     while (tmp_mm == 0xFF){   
  46.         tmp_mm = usart_input_threshold(59);
  47.         rtc_initpara.rtc_minute = tmp_mm;
  48.     }
  49.     printf("  %0.2x\n\r", tmp_mm);

  50.     printf("  please input second:\n\r");
  51.     while (tmp_ss == 0xFF){
  52.         tmp_ss = usart_input_threshold(59);
  53.         rtc_initpara.rtc_second = tmp_ss;
  54.     }
  55.     printf("  %0.2x\n\r", tmp_ss);

  56.     /* RTC current time configuration */
  57.     if(ERROR == rtc_init(&rtc_initpara)){   
  58.         printf("\n\r** RTC time configuration failed! **\n\r");
  59.     }else{
  60.         printf("\n\r** RTC time configuration success! **\n\r");
  61.         rtc_show_time();
  62.         RTC_BKP0 = BKP_VALUE;
  63.     }  
  64. }

  65. /*!
  66.     \brief      display the current time
  67.     \param[in]  none
  68.     \param[out] none
  69.     \retval     none
  70. */
  71. void rtc_show_time(void)
  72. {
  73.     uint32_t time_subsecond = 0;
  74.     uint8_t subsecond_ss = 0,subsecond_ts = 0,subsecond_hs = 0;

  75.     rtc_current_time_get(&rtc_initpara);  

  76.     /* get the subsecond value of current time, and convert it into fractional format */
  77.     time_subsecond = rtc_subsecond_get();
  78.     subsecond_ss=(1000-(time_subsecond*1000+1000)/400)/100;
  79.     subsecond_ts=(1000-(time_subsecond*1000+1000)/400)%100/10;
  80.     subsecond_hs=(1000-(time_subsecond*1000+1000)/400)%10;
  81.    
  82.     printf("Current time: 20%0.2x-%0.2x-%0.2x %0.2x:%0.2x:%0.2x .%d%d%d \n\r", \
  83.                                         rtc_initpara.rtc_year, rtc_initpara.rtc_month , rtc_initpara.rtc_date,\
  84.           rtc_initpara.rtc_hour, rtc_initpara.rtc_minute, rtc_initpara.rtc_second,\
  85.           subsecond_ss, subsecond_ts, subsecond_hs);
  86. }

  87. /*!
  88.     \brief      get the input character string and check if it is valid
  89.     \param[in]  none
  90.     \param[out] none
  91.     \retval     input value in BCD mode
  92. */
  93. uint8_t usart_input_threshold(uint32_t value)
  94. {
  95.     uint32_t index = 0;
  96.     uint32_t tmp[2] = {0, 0};

  97.     while (index < 2){
  98.         while (RESET == usart_flag_get(USART1, USART_FLAG_RBNE));
  99.         tmp[index++] = usart_data_receive(USART1);
  100.         if ((tmp[index - 1] < 0x30) || (tmp[index - 1] > 0x39)){
  101.             printf("\n\r please input a valid number between 0 and 9 \n\r");
  102.             index--;
  103.         }
  104.     }

  105.     index = (tmp[1] - 0x30) + ((tmp[0] - 0x30) * 10);
  106.     if (index > value){
  107.         printf("\n\r please input a valid number between 0 and %d \n\r", value);
  108.         return 0xFF;
  109.     }
  110.    
  111.     index = (tmp[1] - 0x30) + ((tmp[0] - 0x30) <<4);
  112.     return index;
  113. }


主函数检测和串口显示代码:
  1. /* check if RTC has aready been configured */
  2.                         if (BKP_VALUE != RTC_BKP0){   
  3.                                         rtc_setup();
  4.                         }else{
  5.                                         /* detect the reset source */
  6.                                         if (RESET != rcu_flag_get(RCU_FLAG_PORRST)){
  7.                                                         printf("power on reset occurred....\n\r");
  8.                                         }else if (RESET != rcu_flag_get(RCU_FLAG_EPRST)){
  9.                                                         printf("external reset occurred....\n\r");
  10.                                         }
  11.                                         printf("no need to configure RTC....\n\r");

  12.                                         rtc_show_time();
  13.                         }
  14.                         rcu_all_reset_flag_clear();


最终设置完成后的运行效果:

    RTC.png       
微信图片_20180921142247.jpg

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复