当前位置: 首页 > news >正文

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库中的mktimelocaltime用于时间格式转换(日期时间 ? 秒计数器),需包含头文件#include <time.h>

二. 初始化(支持LSE/LSI两种时钟源,默认LSE)

2.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.768KHz)while(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(内部低速晶振,约40KHz)while(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/LSI),LSE为外部32.768KHz晶振,可由备用电源供电(主电源掉电后仍能走时);LSI为内部40KHz晶振,无需外部硬件,但主电源掉电后停止走时。

  • 备份域访问:RTC和BKP(备份寄存器)属于备份域,需先开启PWR和BKP时钟,再通过PWR_BackupAccessCmd(ENABLE)开启访问权限,否则无法操作RTC和备份寄存器。

  • 第一次配置判断:通过备份寄存器BKP_DR1写入标志位0xA5A5,下次上电时读取该标志位,避免重复初始化(重复初始化会覆盖已设置的时间)。

  • 同步与等待:RTC_WaitForSynchro()用于等待RTC与APB1总线同步(避免读写时序错乱);RTC_WaitForLastTask()用于等待RTC操作完成(RTC操作是异步的,需等待确认)。

  • 预分频器配置:预分频器值 = 时钟频率 - 1,LSE(32768KHz)对应32768-1,LSI(40KHz)对应40000-1,分频后RTC计数频率为1Hz(每秒计数1次),对应时间的秒单位。

三. 核心函数用法

  1. MyRTC_Initvoid MyRTC_Init(void);
    函 数:RTC初始化(含时钟源配置、备份域使能、第一次配置判断)
    作用:初始化RTC相关时钟和GPIO,判断是否为第一次配置,第一次配置则开启时钟源、设置预分频器、初始化时间并写入标志位;非第一次配置则直接完成同步,确保RTC正常工作。
    补充:默认使用LSE时钟源,LSE无法起振时,替换为LSI版本的初始化函数。

  2. MyRTC_SetTimevoid MyRTC_SetTime(void);函 数:RTC设置时间
    作用:将全局数组MyRTC_Time(格式:年、月、日、时、分、秒)的时间值,刷新到RTC硬件电路。
    核心逻辑:通过mktime函数将日期时间结构体转换为秒计数器(从1970年1月1日00:00:00开始的总秒数),减去86060(东八区时区调整),再通过RTC_SetCounter写入RTC计数器,完成时间设置。

  3. 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会重新执行第一次配置,覆盖原有时间。

  • 时区调整:mktimelocaltime函数默认使用UTC时间(世界标准时间),需通过±86060(8小时)调整为东八区时间,否则读取的时间会比实际时间晚8小时。

  • 同步与等待函数:RTC_WaitForSynchro()RTC_WaitForLastTask()不可省略,否则会导致RTC读写时序错乱,出现时间设置失败、读取数据异常等问题。

  • 备用电源:使用LSE时钟源时,若接入备用电源(如纽扣电池),主电源掉电后RTC仍能正常走时;使用LSI时钟源时,备用电源无效。

  • 时间格式:全局数组MyRTC_Time的年份需传入4位(如2023),月份、日期、时、分、秒需传入实际值(月份1-12,日期1-31,时0-23,分0-59,秒0-59),MyRTC_SetTime会自动适配tm结构体的格式(年份-1900,月份-1)。

  • 头文件依赖:需包含time.h头文件,否则mktimelocaltime函数会报错,需确保编译器支持该头文件。

http://www.jsqmd.com/news/694166/

相关文章:

  • 程序员必看!网络安全薪资高达5万+,这份免费学习资源助你转行高薪领域,建议收藏!
  • ESXi 5.5存储爆满导致vSphere Client报503?别慌,手把手教你从底层释放空间并重启服务
  • 【ARM平台实战】Qt5.14.2源码编译与QtWebEngine模块深度集成指南
  • OpenHarmony实战-从模拟器到真机:开发板应用调试全链路解析
  • 智能分析是什么?一文拆解智能分析应用落地!
  • 企业内网通讯软件:筑牢政企数字安全底座,开启协同新范式
  • PowerShell 批量改名脚本
  • nxdumptool 终极指南:Switch游戏备份工具完全教程
  • Python调用外部程序实战:从os.system到subprocess的进阶指南
  • 3分钟快速上手QKeyMapper:游戏手柄映射键盘鼠标的终极指南
  • opencv —python
  • 嘉立创DEA:移除全部泪滴
  • 快手万人组织的 AI 研发范式跃迁和落地实践
  • 如何用Zotero PDF Translate高效突破学术文献语言障碍?
  • 反爬升级后,单纯更换代理IP还够用吗?实测分析
  • 生态学家的R语言实战:用rWCVP从物种名录到发表级分布地图
  • 《深入浅出通信原理》连载006-010
  • MiniCPM-O-4_5-GGUF 全解析
  • 别再只看平均延迟了!用FIO的percentile_list参数,精准评估你的SSD服务质量(QoS)
  • 搞懂GNSS定位精度:手把手教你处理GPS/BDS的TGD和DCB参数(附Python代码示例)
  • 应对Turnitin严查:英文论文降AIGC率不踩坑的正确方法(附实操达标教程)
  • 告别玄学调参:用FPGA+Verilog仿真DDR3的突发读写与预取机制
  • Elasticsearch管理难题?ES-Client桌面客户端让索引管理与查询调试更高效
  • Redis数据结构-动态字符串
  • 嘉立创EDA:增加泪滴和铺铜以后,出现大量告警,通过重建所有铺铜来解决(包含内电层)
  • 2026年石笼网及相关产品厂家推荐:安平县铭邦金属丝网制造有限公司,石笼网兜、格宾石笼等全系供应 - 品牌推荐官
  • 网络安全薪资揭秘:小白如何逆袭30万年薪,必看收藏
  • VSCode+Python+遥感影像处理实战配置(农业AI工程师私藏版)
  • 2026年家用电梯厂家推荐:上海益到家科技有限公司,简易好安装好折叠电梯、座椅电梯等全系供应 - 品牌推荐官
  • 学术英语语境重构!英文论文降AI工具实测:如何从底层逻辑摆脱AIGC感?