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 */ } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具