蓝桥杯嵌入式之RTC讲解

RTC是实时时钟的简称,可以产生秒、分、时等信息。在蓝桥杯嵌入式比赛中也是比较常考的一个知识点。

RTC初始化讲解

RTC的初始化需要stm32f10x_rtc.c、stm32f10x_rtc.h、stm32f10x_rcc.c、stm32f10x_rcc.h、misc.c、misc.h、stm32f10x_bkp.c、stm32f10x_bkp.h、stm32f10x_pwr.c和stm32f10x_pwr.h。

RTC初始化代码为

/**
  * @说明     配置RTC
  * @参数     None
  * @返回值   None
  */
void RTC_Configuration(void)
{
  /* Enable PWR and BKP clocks */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

  PWR_BackupAccessCmd(ENABLE);
  BKP_DeInit();
  RCC_LSICmd(ENABLE);
  /* Wait till LSE is ready */
  while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);
  
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
  RCC_RTCCLKCmd(ENABLE);

  RTC_WaitForSynchro();
  RTC_WaitForLastTask();
  /* Enable the RTC Second */
  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) */
  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();
  
  RTC_SetCounter(HH*3600+MM*60+SS);
  RTC_WaitForLastTask();
}

其中HH、MM、SS表示设置的时、分、秒,在main.c开头定义为

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

函数RTC_SetCounter定义在stm32f10x_rtc.c中的第145行,声明在stm32f10x_rtc.c中的第107行。函数RTC_WaitForLastTask定义在stm32f10x_rtc.c中的第207行,声明在stm32f10x_rtc.c中的第111行。

可以参考CT117E嵌入式竞赛板\STM32_MCU\stm32f10x_stdperiph_lib\STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\RTC\LSI_Calib中的main.c文件。

源代码为

/**
  * @brief  Configures the RTC.
  * @param  None
  * @retval None
  */
void RTC_Configuration(void)
{
  /* Enable PWR and BKP clocks */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

  /* Allow access to BKP Domain */
  PWR_BackupAccessCmd(ENABLE);

  /* Reset Backup Domain */
  BKP_DeInit();

  /* Enable the LSI OSC */
  RCC_LSICmd(ENABLE);
  /* Wait till LSI is ready */
  while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
  {}
  /* Select the RTC Clock Source */
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);

  /* Enable RTC Clock */
  RCC_RTCCLKCmd(ENABLE);

  /* Wait for RTC registers synchronization */
  RTC_WaitForSynchro();

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();

  /* Enable the RTC Second */
  RTC_ITConfig(RTC_IT_SEC, ENABLE);

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();

  /* Set RTC prescaler: set RTC period to 1sec */
  RTC_SetPrescaler(40000);

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();

  /* To output second signal on Tamper pin, the tamper functionality
       must be disabled (by default this functionality is disabled) */
  BKP_TamperPinCmd(DISABLE);

  /* Enable the RTC Second Output on Tamper Pin */
  BKP_RTCOutputConfig(BKP_RTCOutputSource_Second);
}

只需将函数RTC_SetPrescaler的参数40000改成39999,将最后两个函数改成时钟设置函数。

RTC中断设置

RTC中断设置代码为

/**
  * @说明     配置中断向量控制器
  * @参数     None
  * @返回值   None
  */
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  /* Enable the RTC Interrupt */
  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);
}

源代码为

/**
  * @brief  Configures the nested vectored interrupt controller.
  * @param  None
  * @retval None
  */
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Configure one bit for preemption priority */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  /* Enable the RTC Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  /* Enable the TIM5 Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

只需将结构体NVIC_InitStructure的元素NVIC_IRQChannelPreemptionPriority 的值改为1。去掉TIM5的中断设置。

RTC中断处理函数改写

RTC的中断处理函数仍然是在stm32f10x_it.c文件中编写。

代码为

/**
  * @brief  This function handles PPP interrupt request.
  * @param  None
  * @retval None
  */
void RTC_IRQHandler(void)
{
  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){
      RTC_SetCounter(0x0);
      RTC_WaitForLastTask();
    }
  }
}

函数RTC_GetCounter定义在stm32f10x_rtc.c中的第133行,声明在stm32f10x_rtc.c中的第106行。表示满足一天的时间,需要对时、分、秒全部置零。

源代码为

/**
  * @brief  This function handles RTC global interrupt request.
  * @param  None
  * @retval None
  */
void RTC_IRQHandler(void)
{
  if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
  {
    /* Clear the RTC Second interrupt */
    RTC_ClearITPendingBit(RTC_IT_SEC);

    /* Toggle LED1 */
    STM_EVAL_LEDToggle(LED1);

    /* Enable time update */
    TimeDisplay = 1;

    /* Wait until last write operation on RTC registers has finished */
    RTC_WaitForLastTask();
    
  }
}

其中变量TimeDisplay 为秒数改变标志位,在stm32f10x_it.c定义为

extern uint32_t TimeDisplay;

在main.c中定义为

uint32_t TimeDisplay = 0;

只需将代码STM_EVAL_LEDToggle(LED1);去掉,在if语句内添加判断当前的时间是否达到一天的时间,即24时0分0秒。如果是,则从0时0分0秒开始计算。

RTC时间显示讲解

RTC时间是以秒计算的,即秒数不停的加一,没有分和时的概念,需要进行转换。

RTC时间显示及时分转换的代码为

/**
  * @说明     显示当前时间
  * @参数     TimeVar:RTC Counter值
  * @返回值   None
  */
uint8_t text[20];
void Time_Display(u32 TimeVar)
{
  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((char *)text,"Time: %0.2d:%0.2d:%0.2d",THH, TMM, TSS);
  LCD_DisplayStringLine(Line7,text);
}

原文发布于微信公众号 - IT界的小白帽(l1084504793)

原文发表时间:2019-05-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券