STM32 RTC模块的使用

1 STM32 实时时钟RTC原理

    A 外部晶振采用32.768KHz的原因,因为2的15次方2^15=32768, 所以32.768KHz分频15次后刚好是1Hz,1S就是1Hz。

    B RTC模块有一个实时计数器Real Time Counter,它对震荡源脉冲计数,每个脉冲计数器加1,所以不能从该计数器直接获取时间时、分、秒。

    C STM32F103系列的RTC是不带时间、日期寄存器的,只有STM32F4系列的才有时间、日期寄存器。

    D STM32F103系列MCU提供了一个秒中断源和一个闹钟中断源,修改计数器的值可以重新设置系统当前的时间和日期. RTC模块之所以具有实时时钟功能,是因为它内部维持了一个独立的定时器,通过配置,可以让它准确地每秒钟中断一次。但实际上,RTC就只是一个定时器而已,掉电之后所有信息都会丢失,因此我们需要找一个地方来存储这些信息,于是就找到了备份寄存器。其在掉电后仍然可以通过纽扣电池供电,所以能时刻保存这些数据。

2 调试过程:

 HAL RTC按如下设置后无法产生秒中断。

A 排除32.768K晶振的原因,32.768K晶振如果不配置成RTC的时钟,示波器在该晶振上测不到32.768K的波形。所以首先要将32.768K外部时钟配置为RTC的时钟,晶振才会起震,这和外部8M高速晶振并不相同。

B RTC配置成外部32.768K时钟后,如果硬件不焊接32.768K时钟,则软件会死机,进入错误。

C 在RTC初始化里设置RTC当前时间,并使能秒中断,再调试运行后可以正常进入秒中断了。

 

RTC_TimeTypeDef sTime ={0,0,0};
HAL_RTC_SetTime(&hrtc,&sTime, RTC_FORMAT_BIN);
hrtc.Instance->CRH |=0x01;

 3 使用示例:

 3.1 程序上电初始化部分调用MX_RTC_Init()函数初始化RTC。

    MX_RTC_Init();
   
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

 
  }

3.2 RTC秒中断里添加相应的处理函数。

/**
  * @brief This function handles RTC global interrupt.
  */
void RTC_IRQHandler(void)
{
  /* USER CODE BEGIN RTC_IRQn 0 */

  /* USER CODE END RTC_IRQn 0 */
  HAL_RTCEx_RTCIRQHandler(&hrtc);
  /* USER CODE BEGIN RTC_IRQn 1 */
  sec_timer_flag=1;
 
  /* USER CODE END RTC_IRQn 1 */
}

4 模块代码:

rtc.h

/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __RTC_H__
#define __RTC_H__

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

extern RTC_HandleTypeDef hrtc;

/* USER CODE BEGIN Private defines */

/* USER CODE END Private defines */

void MX_RTC_Init(void);

/* USER CODE BEGIN Prototypes */

/* USER CODE END Prototypes */

#ifdef __cplusplus
}
#endif

#endif /* __RTC_H__ */

rtc.c

/* Includes ------------------------------------------------------------------*/
#include "rtc.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

RTC_HandleTypeDef hrtc;

/* RTC init function */
void MX_RTC_Init(void)
{

  /* USER CODE BEGIN RTC_Init 0 */

  /* USER CODE END RTC_Init 0 */

  /* USER CODE BEGIN RTC_Init 1 */

  /* USER CODE END RTC_Init 1 */

  /** Initialize RTC Only
  */
  hrtc.Instance = RTC;
  hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
  hrtc.Init.OutPut = RTC_OUTPUTSOURCE_SECOND;/* RTC_OUTPUTSOURCE_NONE  ,TAMPER上无输出*/
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN RTC_Init 2 */

  /* USER CODE END RTC_Init 2 */

}

void HAL_RTC_MspInit(RTC_HandleTypeDef* rtcHandle)
{

  if(rtcHandle->Instance==RTC)
  {
  /* USER CODE BEGIN RTC_MspInit 0 */
    RTC_TimeTypeDef sTime ={0,0,0};
//    RTC_AlarmTypeDef sAlarm
  /* USER CODE END RTC_MspInit 0 */
    HAL_PWR_EnableBkUpAccess();
    /* Enable BKP CLK enable for backup registers */
    __HAL_RCC_BKP_CLK_ENABLE();
    /* RTC clock enable */
    __HAL_RCC_RTC_ENABLE();

    /* RTC interrupt Init */
    HAL_NVIC_SetPriority(RTC_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(RTC_IRQn);
  /* USER CODE BEGIN RTC_MspInit 1 */

     
     HAL_RTC_SetTime(&hrtc,&sTime, RTC_FORMAT_BIN);
     hrtc.Instance->CRH |=0x01;
  /* USER CODE END RTC_MspInit 1 */
  }
}

void HAL_RTC_MspDeInit(RTC_HandleTypeDef* rtcHandle)
{

  if(rtcHandle->Instance==RTC)
  {
  /* USER CODE BEGIN RTC_MspDeInit 0 */

  /* USER CODE END RTC_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_RTC_DISABLE();

    /* RTC interrupt Deinit */
    HAL_NVIC_DisableIRQ(RTC_IRQn);
  /* USER CODE BEGIN RTC_MspDeInit 1 */

  /* USER CODE END RTC_MspDeInit 1 */
  }
}

 

posted @ 2023-10-14 16:27  okyihu  阅读(126)  评论(0编辑  收藏  举报