MDK环境准备:win10+MDK536
开发板型号: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);
}
}
运行效果:
原作者:zlywit