TA的每日心情 | 奋斗 2024-9-22 22:20 |
---|
签到天数: 944 天 连续签到: 1 天 [LV.10]以坛为家III
|
液晶屏成功驱动后,首先想到的是做一个闹钟。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;
}
}
在调试过程中,发现时间总是不能写到寄存器里,每次写入都会出现错误,后来给板子断电后,重新上电,就可以将时间写入寄存器内,这里应该是由于备份寄存器写保护了,还需要去查一下才可以确认
|
|