蓝桥杯嵌入式——实时时钟RTC

基础知识

介绍

RTC是STM32的一个独立定时器,在相应软件配置下可以实现时钟日历的功能。蓝桥杯对RTC主要考察他的时钟功能,具体可以参考嵌入式第九届的省赛题。对RTC的考察并不难,但也必须要掌握。
需要记住的是RTC和普通定时器不一样的地方:RTC模块和时钟配置系统是在后备区域,即在系统复位或从待机模式唤醒后,RTC的设置和时间维持不变。但在系统复位后会禁止访问后备寄存器和RTC,以防止对后备区域的意外操作,所以在设置RTC之前要去掉备份区域写保护。(这些内容在STM32参考手册都有些写,我希望大家能够熟练使用参考手册,无论做客观题还是主观题都是非常有用的!

RTC配置步骤:

  1. 使能PWR和BKP时钟
  2. 使能后备寄存器访问
  3. 配置RTC时钟源并使能RTC时钟
  4. 配置RTC预分频系数
  5. 设置时间
  6. 开启相关中断
  7. 编写中断服务函数
  8. 注意:部分操作要等待写操作完成和同步

代码:

在RTC驱动文件中是下面这个:

#define HH 11  //时
#define MM 59  //分
#define SS 50  //秒

extern uint32_t TimeDisplay;//标志位,在产生秒中断时更新时间

void RTC_Config()
{
    
    
 NVIC_InitTypeDef NVIC_InitStructure;
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE);//使能PWR和BKP的时钟
 PWR_BackupAccessCmd(ENABLE);//使能后备寄存器访问
 BKP_DeInit();
 
 RCC_LSICmd(ENABLE);//选择LSI为时钟
 while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);//等待LSI低速时钟准备就绪
 
 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
 
 RCC_RTCCLKCmd(ENABLE);
 RTC_WaitForSynchro(); //等待同步
 RTC_WaitForLastTask(); //等待写完成
 
 RTC_ITConfig(RTC_IT_SEC, ENABLE);
 RTC_WaitForLastTask();//等待写完成
 /* Set RTC prescaler: set RTC period to 1sec */
 RTC_SetPrescaler(39999); /* RTC period = RTCCLK/RTC_PR = (40 KHz)/(39999+1) */
 RTC_WaitForLastTask();//等待写完成
 
 RTC_SetCounter(HH*3600+MM*60+SS);//设置时间
 RTC_WaitForLastTask();//等待写完成
 
 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组1

 NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 NVIC_Init(&NVIC_InitStructure); 
 }
 void Time_Display(u32 TimeVar)//LCD显示函数
{
    
    
 char text[20];
 u32 THH = 0, TMM = 0, TSS = 0;
  /* Compute  hours */
 THH = TimeVar / 3600;
 /* Compute minutes */
 TMM = (TimeVar % 3600) / 60;
 /* Compute seconds */
 TSS = (TimeVar % 3600) % 60;
  sprintf(text,"Time: %0.2d:%0.2d:%0.2d",THH, TMM, TSS);
 LCD_DisplayStringLine(Line6,(u8 *)text);
 }
void RTC_IRQHandler(void)//RTC的秒中断
{
    
    
  if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
  {
    
    
  RTC_ClearITPendingBit(RTC_IT_SEC);
  TimeDisplay = 1;  //时间更新标志置位
    /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();
    /* 23:59:59 */
  if (RTC_GetCounter() == 0x00015180)//写成24*3600也是可以的
  {
    
    
   RTC_SetCounter(0x0);
   RTC_WaitForLastTask();
  }
 }
}

在主函数这样写:

 while(1)
 {
    
    
  if(TimeDisplay == 1)//RTC计数器每加1s,会进入中断更新标志位,在主函数中便会显示当前计数器的值。
  {
    
    
   Time_Display(RTC_GetCounter());
   TimeDisplay = 0;  //清除标志位
  }
 }

效果展示

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43690936/article/details/105317394