zlywit · 2023年02月05日 · 湖北

【GD32F427开发板试用】+RTC实时时钟

MDK环境准备:win10+MDK536
开发板资料:https://aijishu.com/a/1060000...
开发板型号:GD32427R_START V1.0
试用功能描述:利用主芯片内部的RTC模块设计一个实时闹钟,利用USART1显示年、月、日、时、分、秒的配置过程以及闹钟时、分、秒配置信息,板上LED1灯默认灭,当闹钟时间到了亮灯提示。
编程步骤:
(1)LED1灯的初始化
(2)USART1串口的初始化
(3)RTC和闹钟的配置
(4)主程序和闹钟中断

部分主要代码:
(1)LED1灯的初始化

/* enable the LEDs GPIO clock */
rcu_periph_clock_enable(RCU_GPIOC);    

/* configure LED1 GPIO port */
gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
/* reset LED1 GPIO pin */
gpio_bit_reset(GPIOC, GPIO_PIN_6);

/* turn off LED1 */
gpio_bit_reset(GPIOC, GPIO_PIN_6);

(2)USART1串口的初始化

  /*USART1  initial */
  rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_USART1);

  //rcu_periph_clock_enable(RCU_SYSCFG);
 
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2 | GPIO_PIN_3);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2 | GPIO_PIN_3);
gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_2 | GPIO_PIN_3);    

  usart_deinit(USART1);
usart_baudrate_set(USART1, 115200U);
usart_receive_config(USART1, USART_RECEIVE_ENABLE);
usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);
usart_enable(USART1);

(3)RTC和闹钟的配置

/* enable PMU clock */
rcu_periph_clock_enable(RCU_PMU);  //APB1EN 28bit PMUEN 
/* enable the access of the RTC registers */
pmu_backup_write_enable();

rtc_pre_config();
/* get RTC clock entry selection */
RTCSRC_FLAG = GET_BITS(RCU_BDCTL, 8, 9);

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

RTC相关修改子函数:
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);
//32KHz  -->  1Hz
      prescaler_s = 0x13F;  //319
      prescaler_a = 0x63;    //99
#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); //enable RTC APB1 clock 
rtc_register_sync_wait();  

}

void rtc_setup(void)
{

uint32_t tmp_yy = 0xFF, tmp_mon = 0xFF, tmp_dd = 0xFF;  

/* 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;

  printf("\n\rCurrent date: %0.2x/%0.2x/%0.2x \n\r", \
      rtc_initpara.year, rtc_initpara.month, rtc_initpara.date);

  printf("\n\r=======Configure RTC Date========\n\r");

printf("\n\r please input year(00-99):\n\r");
while (0xFF == tmp_yy){
    tmp_yy = usart_input_threshold(99);
    rtc_initpara.year = tmp_yy;
}
printf("  %0.2x\n\r", tmp_yy);    

    printf("\n\r please input month(01-12):\n\r");
while (0xFF == tmp_mon){
    tmp_mon = usart_input_threshold(12);
    rtc_initpara.month = tmp_mon;
}
printf("  %0.2x\n\r", tmp_mon);
    
    printf("\n\r please input date(01-31):\n\r");
while (0xFF == tmp_dd){
    tmp_dd = usart_input_threshold(31);
    rtc_initpara.date = tmp_dd;
}
printf("  %0.2x\n\r", tmp_dd);        

  printf("\n\rCurrent date: %0.2x/%0.2x/%0.2x \n\r", \
      rtc_initpara.year, rtc_initpara.month, rtc_initpara.date);
    
/* current time input */
printf("\n\r=======Configure RTC Time========\n\r");
printf("\n\r please input hour(00-23):\n\r");
while (0xFF == tmp_hh){
    tmp_hh = usart_input_threshold(23);
    rtc_initpara.hour = tmp_hh;
        //printf("\n\rtmp_hh==  %0.2x\n\r", tmp_hh);
}
printf("  %0.2x\n\r", tmp_hh);

printf("\n\r  please input minute:\n\r");
while (0xFF == tmp_mm){
    tmp_mm = usart_input_threshold(59);
    rtc_initpara.minute = tmp_mm;
}
printf("  %0.2x\n\r", tmp_mm);

printf("\n\r  please input second:\n\r");
while (0xFF == tmp_ss){
    tmp_ss = usart_input_threshold(59);
    rtc_initpara.second = tmp_ss;
}
printf("  %0.2x\n\r", tmp_ss);

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

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

rtc_alarm_disable(RTC_ALARM0);
printf("\n\r =======Input Alarm Value======= \n\r");
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 */
printf("\n\r  please input Alarm Hour:\n\r");
while (0xFF == tmp_hh){
    tmp_hh = usart_input_threshold(23);
    rtc_alarm.alarm_hour = tmp_hh;
}
printf("  %0.2x\n\r", tmp_hh);

printf("\n\r  Please Input Alarm Minute:\n\r");
while (0xFF == tmp_mm){
    tmp_mm = usart_input_threshold(59);
    rtc_alarm.alarm_minute = tmp_mm;
}
printf("  %0.2x\n\r", tmp_mm);

printf("\n\r  Please Input Alarm Second:\n\r");
while (0xFF == tmp_ss){
    tmp_ss = usart_input_threshold(59);
    rtc_alarm.alarm_second = tmp_ss;
}
printf("  %0.2x\n\r", tmp_ss);

/* RTC alarm configuration */
rtc_alarm_config(RTC_ALARM0,&rtc_alarm);
printf("\n\r** RTC Set Alarm Success!  **\n\r");
rtc_show_alarm();

rtc_interrupt_enable(RTC_INT_ALARM0);
rtc_alarm_enable(RTC_ALARM0);

}

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)%100/10;
subsecond_hs=(1000-(time_subsecond*1000+1000)/400)%10;

printf("\n\r ================================================ \n\r");
printf("\n\rCurrent date(year/month/date): %0.2x / %0.2x / %0.2x \n\r", \
      rtc_initpara.year, rtc_initpara.month, rtc_initpara.date);
printf("\n\rCurrent time(hour:minute:second): %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);

}

void rtc_show_alarm(void)
{

rtc_alarm_get(RTC_ALARM0,&rtc_alarm);
  printf("\n\r ================================================ \n\r");
printf("\n\rThe alarm time: %0.2x:%0.2x:%0.2x \n\r", rtc_alarm.alarm_hour, rtc_alarm.alarm_minute,\
       rtc_alarm.alarm_second);

}

uint8_t usart_input_threshold(uint32_t value)
{

uint32_t index = 0;
uint32_t tmp[2] = {0, 0};

while (index < 2){
    while (RESET == usart_flag_get(USART1, USART_FLAG_RBNE));
    tmp[index++] = usart_data_receive(USART1);
          usart_flag_clear(USART1,USART_FLAG_RBNE);
        
          //printf("\n\r index=%d \n\r",index);
          //printf("\n\r tmp[index - 1]=%d \n\r",tmp[index - 1]);
        
    if ((tmp[index - 1] < 0x30) || (tmp[index - 1] > 0x39)){
        printf("\n\r please input a valid number between 0 and 9 \n\r");
        index--;
    }
}

index = (tmp[1] - 0x30) + ((tmp[0] - 0x30) * 10);
if (index > value){
    printf("\n\r please input a valid number between 0 and %d \n\r", value);
    return 0xFF;
}

index = (tmp[1] - 0x30) + ((tmp[0] - 0x30) <<4);
return index;

}

(4)主程序和闹钟中断

主程序补充:

/* configure systick */
systick_config();

//LED初始化调用
//USART1初始化调用
//RTC初始化调用

rtc_flag_clear(RTC_FLAG_ALRM0);
exti_flag_clear(EXTI_17);
/* RTC alarm interrupt configuration */
exti_init(EXTI_17,EXTI_INTERRUPT,EXTI_TRIG_RISING);
nvic_irq_enable(RTC_Alarm_IRQn,0,0);        
while(1) ;

闹钟中断函数
void RTC_Alarm_IRQHandler(void)
{

if(RESET != rtc_flag_get(RTC_FLAG_ALRM0)){
    rtc_flag_clear(RTC_FLAG_ALRM0);
    exti_flag_clear(EXTI_17);
          gpio_bit_set(GPIOC, GPIO_PIN_6);
    UART1_Transmit("\n\rLED1 on...Alarm on...\n\r");
          delay_1ms(1000);
} 

}

运行效果:
image.png
image.png
image.png

主要参考资料:
GD32F4xx_Firmware_Library_V3.0.2/GD32F4xx_Firmware_Library/Examples

试用感受:国产芯片与ST类似芯片编程方法类似,兼容效果好,芯片国产化未来可期!!

推荐阅读
关注数
10707
内容数
187
中国高性能通用微控制器领域的领跑者兆易创新GD系列芯片技术专栏。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息