RTC代码部分
RTC一. 常用库函数void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);void RCC_LSEConfig(uint32_t RCC_LSE);void RCC_LSICmd(FunctionalState NewState);FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG);void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource);void RCC_RTCCLKCmd(FunctionalState NewState);void PWR_BackupAccessCmd(FunctionalState NewState);uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR);void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data);void RTC_WaitForSynchro(void);void RTC_WaitForLastTask(void);void RTC_SetPrescaler(uint32_t PrescalerValue);void RTC_SetCounter(uint32_t CounterValue);uint32_t RTC_GetCounter(void);time_t mktime(struct tm *timeptr);struct tm *localtime(const time_t *timer);补充说明time.h库中的mktime和localtime用于时间格式转换日期时间 ? 秒计数器需包含头文件#include time.h。二. 初始化支持LSE/LSI两种时钟源默认LSE2.1 默认初始化LSE时钟源推荐voidMyRTC_Init(void){/*开启时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//开启PWR时钟控制备份域访问RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);//开启BKP时钟备份寄存器、RTC相关/*备份寄存器访问使能*/PWR_BackupAccessCmd(ENABLE);//开启对备份域BKP、RTC的访问权限// 判断RTC是否为第一次配置通过备份寄存器标志位判断if(BKP_ReadBackupRegister(BKP_DR1)!0xA5A5){RCC_LSEConfig(RCC_LSE_ON);//开启LSE外部低速晶振32.768KHzwhile(RCC_GetFlagStatus(RCC_FLAG_LSERDY)!SET);//等待LSE晶振稳定就绪RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//选择RTC时钟源为LSERCC_RTCCLKCmd(ENABLE);//使能RTC时钟RTC_WaitForSynchro();//等待RTC与APB1总线同步RTC_WaitForLastTask();//等待上一次RTC操作完成保障操作可靠性RTC_SetPrescaler(32768-1);//设置RTC预分频器32768分频后计数频率为1HzRTC_WaitForLastTask();//等待预分频器配置完成MyRTC_SetTime();//初始化时间将全局数组时间写入RTC硬件BKP_WriteBackupRegister(BKP_DR1,0xA5A5);//写入标志位标记已完成第一次配置}else//非第一次配置已初始化过直接同步{RTC_WaitForSynchro();//等待RTC与APB1总线同步RTC_WaitForLastTask();//等待上一次RTC操作完成}}2.2 备用初始化LSI时钟源LSE无法起振时使用voidMyRTC_Init(void){RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);PWR_BackupAccessCmd(ENABLE);if(BKP_ReadBackupRegister(BKP_DR1)!0xA5A5){RCC_LSICmd(ENABLE);//开启LSI内部低速晶振约40KHzwhile(RCC_GetFlagStatus(RCC_FLAG_LSIRDY)!SET);//等待LSI晶振稳定就绪RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);//选择RTC时钟源为LSIRCC_RTCCLKCmd(ENABLE);//使能RTC时钟RTC_WaitForSynchro();RTC_WaitForLastTask();RTC_SetPrescaler(40000-1);//设置预分频器40000分频后计数频率为1HzRTC_WaitForLastTask();MyRTC_SetTime();BKP_WriteBackupRegister(BKP_DR1,0xA5A5);}else{RCC_LSICmd(ENABLE);//非第一次配置也需重新开启LSI时钟while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY)!SET);RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);RCC_RTCCLKCmd(ENABLE);RTC_WaitForSynchro();RTC_WaitForLastTask();}}初始化关键说明时钟配置核心RTC依赖低速时钟LSE/LSILSE为外部32.768KHz晶振可由备用电源供电主电源掉电后仍能走时LSI为内部40KHz晶振无需外部硬件但主电源掉电后停止走时。备份域访问RTC和BKP备份寄存器属于备份域需先开启PWR和BKP时钟再通过PWR_BackupAccessCmd(ENABLE)开启访问权限否则无法操作RTC和备份寄存器。第一次配置判断通过备份寄存器BKP_DR1写入标志位0xA5A5下次上电时读取该标志位避免重复初始化重复初始化会覆盖已设置的时间。同步与等待RTC_WaitForSynchro()用于等待RTC与APB1总线同步避免读写时序错乱RTC_WaitForLastTask()用于等待RTC操作完成RTC操作是异步的需等待确认。预分频器配置预分频器值 时钟频率 - 1LSE32768KHz对应32768-1LSI40KHz对应40000-1分频后RTC计数频率为1Hz每秒计数1次对应时间的秒单位。三. 核心函数用法MyRTC_Initvoid MyRTC_Init(void);函 数RTC初始化含时钟源配置、备份域使能、第一次配置判断作用初始化RTC相关时钟和GPIO判断是否为第一次配置第一次配置则开启时钟源、设置预分频器、初始化时间并写入标志位非第一次配置则直接完成同步确保RTC正常工作。补充默认使用LSE时钟源LSE无法起振时替换为LSI版本的初始化函数。MyRTC_SetTimevoid MyRTC_SetTime(void);函 数RTC设置时间作用将全局数组MyRTC_Time格式年、月、日、时、分、秒的时间值刷新到RTC硬件电路。核心逻辑通过mktime函数将日期时间结构体转换为秒计数器从1970年1月1日00:00:00开始的总秒数减去86060东八区时区调整再通过RTC_SetCounter写入RTC计数器完成时间设置。MyRTC_ReadTimevoid MyRTC_ReadTime(void);函 数RTC读取时间作用读取RTC硬件电路中的当前时间刷新到全局数组MyRTC_Time供主函数调用。核心逻辑通过RTC_GetCounter读取RTC当前的秒计数器加上86060东八区时区调整再通过localtime函数将秒计数器转换为日期时间结构体最后赋值给全局数组。四. 全局变量说明uint16_tMyRTC_Time[]{2023,1,1,23,59,55};//RTC时间全局数组// 数组索引对应[0]年[1]月[2]日[3]时[4]分[5]秒// 用法修改该数组后调用MyRTC_SetTime()即可更新RTC硬件时间调用MyRTC_ReadTime()可将硬件时间读入该数组五. 注意事项LSE晶振注意LSE依赖外部32.768KHz晶振若未焊接晶振或晶振无法起振程序会卡死在while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) ! SET)此时需替换为LSI版本的初始化函数。LSI局限性LSI为内部晶振精度低于LSE且无法由备用电源供电主电源掉电后RTC停止走时再次上电后时间需重新校准。标志位作用备份寄存器BKP_DR1中的0xA5A5是自定义标志位用于判断RTC是否第一次配置若手动清除该标志位或备份域掉电RTC会重新执行第一次配置覆盖原有时间。时区调整mktime和localtime函数默认使用UTC时间世界标准时间需通过±860608小时调整为东八区时间否则读取的时间会比实际时间晚8小时。同步与等待函数RTC_WaitForSynchro()和RTC_WaitForLastTask()不可省略否则会导致RTC读写时序错乱出现时间设置失败、读取数据异常等问题。备用电源使用LSE时钟源时若接入备用电源如纽扣电池主电源掉电后RTC仍能正常走时使用LSI时钟源时备用电源无效。时间格式全局数组MyRTC_Time的年份需传入4位如2023月份、日期、时、分、秒需传入实际值月份1-12日期1-31时0-23分0-59秒0-59MyRTC_SetTime会自动适配tm结构体的格式年份-1900月份-1。头文件依赖需包含time.h头文件否则mktime和localtime函数会报错需确保编译器支持该头文件。