前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >蓝桥杯嵌入式之RTC讲解

蓝桥杯嵌入式之RTC讲解

作者头像
用户5935416
发布2019-08-01 10:08:36
1.4K0
发布2019-08-01 10:08:36
举报
文章被收录于专栏:IT界的小白帽

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初始化代码为

代码语言:javascript
复制
/**
  * @说明     配置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开头定义为

代码语言:javascript
复制
#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文件。

源代码为

代码语言:javascript
复制
/**
  * @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中断设置代码为

代码语言:javascript
复制
/**
  * @说明     配置中断向量控制器
  * @参数     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);
}

源代码为

代码语言:javascript
复制
/**
  * @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文件中编写。

代码为

代码语言:javascript
复制
/**
  * @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行。表示满足一天的时间,需要对时、分、秒全部置零。

源代码为

代码语言:javascript
复制
/**
  * @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定义为

代码语言:javascript
复制
extern uint32_t TimeDisplay;

在main.c中定义为

代码语言:javascript
复制
uint32_t TimeDisplay = 0;

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

RTC时间显示讲解

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

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

代码语言:javascript
复制
/**
  * @说明     显示当前时间
  * @参数     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);
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-05-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT界的小白帽 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档