ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

STM32 RTC掉电保持方案:VBAT供电与备份寄存器详解

STM32 RTC掉电保持方案:VBAT供电与备份寄存器详解 做嵌入式这些年但凡产品里带时间戳、定时上报、日志记录这些功能几乎都躲不开一个经典痛点设备一掉电时间就归零。尤其是批量出货后现场设备突然断电再上电系统时间直接回到2000年轻则日志错乱重则影响业务逻辑判断。很多第一次接触RTC的朋友会先想到用外部RTC芯片比如DS1302、PCF8563这当然是一种方案但对于已经有STM32的板子来说其实还藏着一个更省成本、更省布板面积的方案——用芯片自带的RTC外设配合VBAT引脚外接一颗纽扣电池或法拉电容就能实现掉电时钟不中断。这篇文章我会从硬件电路怎么接、电池怎么选到软件初始化怎么写、代码每一行的作用是什么再到实际掉电测试的验证方法和常见坑完整走一遍。内容面向的是已经会点STM32基础开发、想给项目加上可靠时钟保持功能的工程师也适合准备用STM32做毕业设计或比赛作品的同学参考。1. 先搞清楚RTC为什么能在断电后继续走VBAT供电域的切换逻辑很多人第一次看原理图会疑惑一个问题芯片都断电了RTC凭什么还能工作答案就在STM32的电源系统架构里。STM32内部并不是只有一个单一的电源域而是根据“是否需要掉电保持”把电路分成了多个区域。VBAT这一路专门给RTC、备份寄存器和部分唤醒逻辑供电芯片主电源VDD切断后内部的电源开关会自动切换到VBAT由外部电池继续给这几个模块供电。1.1 VBAT和VDD之间的电源切换机制STM32的电源设计里VDD是主供电一般接3.3V。VBAT是备份域电源正常情况下可以接和VDD相同的3.3V也可以单独接电池。关键点在于芯片内部有一个电源切换电路当VDD存在且高于阈值时系统使用VDD给备份域供电当VDD掉到阈值以下或完全消失时备份域自动切换到VBAT。这个切换是硬件自动完成的不需要软件参与但有一个前提条件VBAT引脚上必须挂着有效的电源否则切换过去等于白搭。另外需要留意的是VBAT的电压范围在数据手册里有明确标注一般支持1.8V到3.6V也就是说一颗CR2032纽扣电池标称3.0V、一颗LIR2032充电电池标称3.6V、甚至两节AA电池串联都在允许范围内。但不要直接接5V会超出绝对最大额定值。1.2 备份域里到底有哪些数据会被保存搞清楚VBAT供电域里有什么你才能设计好掉电保存的策略。STM32的备份域主要包括三部分RTC寄存器时间计数器和配置寄存器掉电期间RTC继续走时本质上是这些寄存器还在被32.768kHz时钟驱动更新。20个备份数据寄存器BKP_DRx以标准库中的BKP模块来说可以保存20个16位的数据用来记录掉电次数、设备状态等信息。这部分数据在掉电后仅依靠VBAT供电也可以长期保存。RTC闹钟寄存器和唤醒定时器寄存器如果在低功耗模式下使用RTC闹钟唤醒这些配置也需要在掉电期间保留。有一点容易踩坑很多人以为备份域数据是“无限期”保存的其实不是。备份寄存器和RTC寄存器的数据能否保持完全取决于VBAT电流消耗和电池容量。STM32在VBAT供电模式下的典型电流大约是1.4uA到3uA具体看型号和工作状态如果用的是220mAh左右的CR2032理论上可以维持好几万小时但实际要考虑电池自放电、温度影响不能按理论值算得过于乐观。1.3 为什么不能把VBAT直接和VDD短接有些开发板为了省事把VBAT引脚直接和VDD连在一起这种做法在“不断电开发调试”的场景下没有问题因为只要VDD在RTC就不会丢时间。但你一旦拔掉USB线或者关掉电源RTC寄存器里的时间就会全部丢失下次上电又回到初始值。原因很简单VBAT上没有独立电源主电源掉电后没有任何电源给RTC模块供电。所以如果你想实现“掉电时钟不中断”VBAT必须单独接电池或大容量电容不能简单和VDD短接。如果只是做开发板验证暂时不想买电池座可以用超级电容法拉电容先顶着后面我会专门讲这个替代方案的参数怎么算。2. VBAT硬件设计纽扣电池、充电电池和法拉电容的选型对比硬件设计是RTC掉电保持的第一道关口。这一节我把主流的三种VBAT供电方案放在一起做一个完整的对比并给出不同需求场景下的推荐选择。很多工程师只关注软件配置结果硬件电路埋了雷等到产品量产后发现电池几个月就没电了再回头补设计就晚了。2.1 三种供电方案对比方案典型型号标称电压容量可充电适用场景一次性纽扣电池CR20323.0V220mAh否断电时间较长、维护方便、能更换电池的产品可充电纽扣电池LIR20323.6V40mAh是设备正常工作时边充边用适合密闭性较好的产品法拉电容1F/5.5V或3.3V2.5V~5.5V等效约0.3mAh1F/3.3V是断电时间在小时级以内、要求免维护的场景从表格里能看出来法拉电容的容量和纽扣电池完全不在一个量级。1F的电容在3.3V下存储的能量大约是0.5 * 1 * 3.3^2 5.445 J换算成毫安时是5.445 / 3600 / 3.3 ≈ 0.00046 Ah 0.46mAh。但实际上电容放电时电压是持续下降的能用的容量比这个还要打折扣。所以法拉电容只适合短时掉电保持比如黑匣子断电后保存关键数据、设备秒级重启保持时钟这类场景很合适如果产品可能断电几天甚至几周还是老老实实上纽扣电池。2.2 经典VBAT电路电池座、隔离二极管和滤波电容的配合给大家一个可以直接抄的参考电路这套电路我验证过多次稳定性不错VBAT引脚 │ ├── C1 0.1uF陶瓷电容靠近引脚放置 │ ├── D11N4148或BAT54阳极接电池正极 │ └── R1 100kΩ可选用于静电泄放 │ BT1CR2032电池座 │ GND几个要点C1是必须的。VBAT引脚作为模拟/备份电源输入对高频噪声敏感。0.1uF电容要尽量靠近VBAT引脚走线短而粗直接连到参考地。D1的作用是防倒灌。如果系统VDD正常工作时而电池电压低于VDDD1可以阻断电流从系统电源流向电池避免电池被充到超过自身电压。但是要注意二极管本身有正向压降CR2032经过1N4148后电压会降到3.0-0.4 ≈ 2.6V左右依然在VBAT工作范围内没太大问题。如果选BAT54肖特基压降更低约0.2V损耗更小。R1不是必须的但有些环境静电干扰比较厉害加一个100kΩ电阻给电池正极一个泄放路径能降低VBAT引脚被ESD打坏的概率。2.3 电池寿命的理论估算与实际修正这是很多工程新人特别容易算错的地方。STM32的VBAT电流消耗不同型号、不同时钟源都不一样。以STM32F103系列为例数据手册上标注的VBAT供电电流LSE开启备份域工作大约是1.4uA左右F4系列会稍微高一点约2.2uA。用这个电流加上电池自身自放电率可以做一个大致估算。以CR2032220mAh为例理论寿命 220mAh / 1.4uA ≈ 157142小时 ≈ 18年实际寿命需要乘以一个折扣系数因为电池自放电CR2032自放电率约每年1%-2%温度影响高温下自放电会显著加快负载不完全是恒定电流上电瞬间会有浪涌根据经验实际寿命大约在5到8年左右足够大多数产品的设计寿命了。但如果你用的是LIR2032这种40mAh的充电电池理论寿命只有 40mAh / 1.4uA ≈ 28571小时 ≈ 3.3年而且这还是在理想情况下。所以LIR2032的设计思路不是“撑很久”而是“设备工作时把电池充满掉电后能撑住短时间就行”。2.4 PCB布局布局细节VBAT走线、电池座位置和干扰源隔离硬件设计中很容易忽略的一个点VBAT的走线不要和晶振、高频信号线平行长距离走线。RTC的LSE晶振32.768kHz是模拟敏感器件VBAT引脚上的噪声如果耦合到晶振引脚会导致RTC走时精度下降甚至停振。我见过一个真实案例某工程师做一块带4G通信模块的板子4G天线距离RTC晶振和VBAT走线比较近结果设备一发射数据RTC就出现秒数跳动异常。后来检查发现是射频干扰通过VBAT走线耦合进RTC电源域导致内部时钟信号被干扰。解决办法是把VBAT走线改成包地处理同时把电池座挪远一点问题才解决。所以PCB布局上建议遵循这几条VBAT走线尽量短必要时包地两侧铺地铜并打地过孔电池座位置尽量远离天线、蓝牙模块、电机驱动等干扰源LSE晶振和VBAT引脚不要放在板子边缘边缘容易受到接触放电影响如果产品外壳是可拆卸的电池仓附近不要走高速信号线3. 系统初始化流程正确区分“首次上电配置”和“掉电后重新唤醒”软件部分的第一个关键决策是如何判断“RTC需不需要重新初始化”。很多新手第一次写RTC代码就在每次上电时都对RTC做全套配置包括使能LSE、选择时钟源、设置预分频器、写入初始时间。这样做的问题是每次断电再上电RTC的时间就会被重置回你写入的那个初始值等于完全没有起到“保持”作用。正确的思路是用备份寄存器当标志位区分首次上电和再次上电。3.1 备份寄存器做标志位的原理与流程备份寄存器BKP_DRx的特点是只要VBAT有电它的内容就不会丢失查到里面的标志值如果等于一个特定魔数比如0xA5A5就说明RTC已经初始化过了不用重复配置直接读取计数器即可。整体流程可以这样设计系统上电先使能PWR和BKP外设时钟使能备份域访问权限标准库是PWR_BackupAccessCmd(ENABLE)判断BKP_ReadBackupRegister(BKP_DR1)是否等于0xA5A5如果是说明RTC已被初始化跳转到“读取模式”开启RTC时钟、等待同步如果不是说明是首次上电需要对RTC做完整初始化写时间再写入标志位这个流程避免了一个常见的坑如果固件升级后你希望能重新校准时间但备份寄存器里的标志位还在那么升级后就会跳过初始化。所以升级策略里你要额外设计一个“强制重新初始化”的机制比如用另一个备份寄存器存固件版本号版本号不匹配就强制重新初始化RTC。3.2 判断上电来源备份域复位标志和RTC标志的正确用法STM32的RTC初始化还有一个容易混乱的地方复位的种类。以F1系列为例复位分为系统复位、电源复位和备份域复位。其中备份域复位Backup Domain Reset会清空RTC寄存器和备份寄存器它可能在以下情况触发软件设置BKP_CTLR中的BPE位使能备份域复位VDD和VBAT同时掉电相当于彻底断电所以在代码里要有意识地区分“系统刚上电”和“备份域刚复位”。你可以通过读取复位状态标志来区分F1系列的库函数是RCC_GetFlagStatus(RCC_FLAG_PORRST)或者检查RCC-CSR寄存器中的RSTFLAG位。但从我们实际项目的角度来说通常不需要做这么细的区分用一个标志位就够了——因为如果备份域被复位过备份寄存器里的魔数会变代码自然会走到完整初始化分支。3.3 使用LSI还是LSE这次不能选错这是一个决定掉电保持能不能实现的关键点。STM32的RTC时钟源有两种常用选择LSE外部32.768kHz晶振功耗低、精度高而且它本身由VBAT供电区域的时钟电路驱动掉电后只要VBAT有电晶振就继续振荡RTC继续走时。LSI内部低速RC振荡器不需要外部晶振省了两个引脚但它在芯片掉电后是不工作的——LSI的供电不归VBAT管主电源掉了它也跟着停。结论很明确如果你想实现VBAT掉电时钟不中断必须使用LSE作为RTC时钟源。很多开发板为了省成本没有焊接LSE晶振用LSI写的RTC程序一旦断电立刻失效用户会认为这个RTC功能是坏的。这个问题我在不少项目里帮人排查过排查到最后发现板子根本没焊晶振代码里却还在等LSE就绪直接卡死。3.4 上电后等待LSE起振别在初始化时卡死LSE晶振起振比HSI、HSE慢得多典型起振时间几百毫秒到一两秒在低温或晶振匹配负载电容过大时起振时间会更长。代码里如果用一个无超时的忙等循环来等待LSE就绪极端情况下会在上电初始化时卡死。我建议的做法是加超时保护uint32_t lse_timeout 0; RCC_LSEConfig(RCC_LSE_ON); while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) RESET) { lse_timeout; if (lse_timeout 0x100000) { // 超时处理可以改用LSI临时运行或者报错 break; } }加超时的目的不是真的想去处理LSE起振失败因为失败通常是硬件问题而是避免程序在异常情况下卡死在while里给调试留出窗口。4. 核心代码逐段拆解从使能备份域到写入时间的完整链路这一部分是全文的重点。我用的示例平台是STM32F103系列标准外设库Standard Peripheral Library的写法为什么不用HAL库因为标准库的代码更接近寄存器操作的本质每一行在做什么一目了然更适合理解原理。你的目标平台如果是F4、F0系列寄存器配置大同小异思路可以直接迁移。4.1 完整初始化代码分步骤讲清每段代码的意图void RTC_Init(void) { // 第1步使能电源管理时钟和备份域时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); // 第2步使能备份域访问相当于解锁备份域的写保护 PWR_BackupAccessCmd(ENABLE); // 第3步检查备份寄存器标志位判断是否需要初始化 if (BKP_ReadBackupRegister(BKP_DR1) ! 0xA5A5) { // 第4步复位备份域确保RTC处于已知状态 RCC_BackupResetCmd(ENABLE); RCC_BackupResetCmd(DISABLE); // 第5步使能LSE外部32.768kHz晶振 RCC_LSEConfig(RCC_LSE_ON); // 第6步等待LSE起振稳定加入超时保护 uint32_t timeout 0; while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) RESET) { timeout; if (timeout 0x100000) { break; } } if (timeout 0x100000) { // 第7步选择LSE作为RTC时钟源并开启RTC时钟 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); RCC_RTCCLKCmd(ENABLE); // 第8步等待RTC寄存器同步和上次写入操作完成 RTC_WaitForSynchro(); RTC_WaitForLastTask(); // 第9步设置预分频器将32.768kHz分频为1Hz RTC_SetPrescaler(32767); RTC_WaitForLastTask(); // 第10步初始时间Unix时间戳例如2024年1月1日0时0分0秒 RTC_SetCounter(1704067200); RTC_WaitForLastTask(); // 第11步写入备份寄存器标志位 BKP_WriteBackupRegister(BKP_DR1, 0xA5A5); } } else { // 第12步RTC已经初始化过重新开启RTC时钟并等待同步 RCC_RTCCLKCmd(ENABLE); RTC_WaitForSynchro(); RTC_WaitForLastTask(); } }4.2 预分频器数值到底填什么为什么是32767而不是32768这个数值问的人特别多。LSE晶振的频率是32768HzRTC计数器的时钟是1Hz所以需要分频系数是32768。但寄存器里填的并不是32768而是32767——因为STM32的预分频器是从0开始计数的分频系数等于寄存器值加1。RTC_SetPrescaler(32767)实际产生的分频是32767 1 32768这样RTC计数器每秒钟加1。如果你理解成“填32768”写入寄存器后实际分频就是32769结果是每秒钟计数值增加约32768/32769秒时钟每天会慢一点点。虽然只差一点但对需要精确计时的产品来说这就是定时误差的来源之一。4.3 时间计数器的本质为什么我们不直接“写入几点几分”STM32的RTC计数器RTC_CNT是一个32位寄存器它维护的不是“时:分:秒”格式而是一个从某个基准时间起经过的秒数也就是Unix时间戳。这样做的好处是通用性好计算时间差非常方便而且C库函数可以直接转换。读取当前时间的方法uint32_t current_timestamp RTC_GetCounter();如果你要把时间戳转换成UTC时间结构体可以自己写算法或者用标准库里的方法。F1标准库本身没直接提供“把时间戳转成日期时间”的现成API但有很多公开的转换算法可参考。核心要点是时间戳 → 天数 → 通过“蔡勒公式”或“格雷戈里算法”推算年/月/日再通过余数算时/分/秒。为了省事很多项目直接把这个转换任务丢给上位机做MCU只负责维护时间戳串口上报时直接发数字。这个方法可行但代价是MCU和上位机必须统一时区处理逻辑否则显示的时间会差8小时东八区时差。4.4 时间设置和读取的封装建议实际产品中不要在主循环里频繁调用RTC_GetCounter()因为RTC寄存器读取过程中需要等待同步如果频繁操作会把LSE时钟域和AHB时钟域之间的同步等待时间拉得很长影响主循环实时性。更好的做法是用一个定时中断如1秒读取一次RTC_GetCounter()然后存到全局变量里业务逻辑统一读这个全局变量而不是直接访问RTC寄存器设置时间时先转换好时间戳再调用RTC_SetCounter()写完立即刷新全局变量这样还能顺便解决一个隐患在读取RTC寄存器时如果发生写操作会导致读回的数据不稳定。把读写都收敛到同一处可以降低出现并发问题的概率。5. 掉电实测记录从断电到复电的完整验证流程代码写完不算完必须做真实的掉电测试。这一节我把自己的完整验证流程、测试中发现的坑以及排查思路分享出来供你在自己的项目中参考。5.1 测试环境搭建为什么要用示波器监控VBAT而不是只靠肉眼我的测试环境STM32F103C8T6最小系统板外接32.768kHz晶振负载电容12.5pFVBAT处焊接CR2032电池座可编程直流电源给VDD供电方便快速断电/上电示波器探头接VBAT引脚观察掉电瞬间VBAT电压的变化串口每秒输出当前时间戳便于在PC端记录为什么必须用示波器观察VBAT因为掉电瞬间VDD下降不是瞬间完成的VBAT上的电压波形可以看出电源切换期间是否有跌落、有没有震荡。如果VBAT电压在VDD切换瞬间出现大幅跌落RTC可能会复位也就失去了保持的意义。5.2 第一轮测试发现LSE停振问题并定位原因第一轮测试的结果让我很意外断电后过约2秒再上电RTC时间倒是没有丢失但重新上电后RTC计时“慢了”几秒。排查思路如下先观察串口打印的时间戳发现掉电前后的秒数差比实际断电时间长用示波器抓VBAT波形确认VBAT电压在掉电期间稳定在2.8V左右没有跌落怀疑是LSE晶振在低压/低功耗模式下停振停振期间RTC计数不增加重新上电后自动恢复进一步确认LSE晶振在VBAT低压供电时振荡幅度比正常供电时要小如果晶振的激励功率不足就会停振。而停振后RTC外设不会主动上报错误它只是静默地停止计数等你重新上电或者调整供电后再次起振。这个坑的根源通常是晶振负载电容选择不当或晶振ESR等效串联电阻太大。我当时的板子用的是普通32768晶振质量一般后来换成ESR低于50kΩ的低功耗专用LSE晶振比如NDK、Epson的型号问题解决。测试还发现其实可以通过读取RTC的写操作状态位RTC_WaitForLastTask()配合检查LSE运行标志位F1部分型号有RTC_GetFlagStatus(RTC_FLAG_SEC)这类函数如果长时间没有秒中断就判定停振软件主动复位RTC外设。5.3 第二轮测试断电时间超过电池保持极限的极端情况为了验证极限情况我故意把CR2032扣下来等几分钟再装回去模拟“电池耗尽”的极端场景。结果符合预期时间归零标志位丢失RTC重新进入完整初始化流程。这个结果告诉我们如果设备允许更换电池软件必须在时间归零后提示用户重新校时如果设备不允许更换电池电池寿命必须大于产品寿命或者采用“临时供电保持主电源续充”的方案5.4 完整验证清单一份可以直接抄的测试表格测试项测试方法通过标准我的实测结果首次上电初始化第一次接电观察串口输出RTC开始正常秒计数通过掉电短时保持断电10秒后重新上电时间连续秒差在1秒以内通过LSE换晶振后掉电长时间保持断电1小时后重新上电时间连续误差在容限内通过电池耗尽恢复取下电池并放电再装回时间归零重新初始化通过VDD上电瞬间VBAT电压示波器观察掉电/上电过程VBAT无跌落、无振荡通过LSE起振超时故意去除LSE晶振测试程序不卡死有超时处理通过按这个表逐项执行整个RTC掉电保持功能才算真正闭环。6. 常见故障排查链从“时间不走了”到“时间丢了”的完整思路项目实际运行中RTC的问题往往不是单一的而是多个因素叠加。我按问题现象分类整理了一套排查链路照着一条条走基本能定位90%的问题。6.1 现象一重新上电后时间回到初始值排查链路测量VBAT引脚对地电压是否正常应为电池电压掉电后仍存在检查电池座的接触是否良好示波器观察掉电瞬间VBAT是否有回落检查软件是否每次上电都执行了完整初始化重点看备份寄存器标志位是否真的写进去了检查是否误用了RCC_BackupResetCmd(ENABLE)这个操作会清空备份域包括标志位和时间确认RTC时钟源选择的是LSE而不是LSI6.2 现象二时间能保持但走时不准确、每天慢/快几秒这是LSE晶振精度和匹配问题不是芯片问题。排查链路用频率计测量LSE引脚输出的32.768kHz频率和标准值对比检查晶振负载电容、匹配电容是否匹配典型的12.5pF负载电容 ≈ 两个6pF-8pF的匹配电容串联检查晶振引脚附近是否有走线引入串扰如果是可调校产品可以考虑在代码里做秒补偿比如每天自动校准一次6.3 现象三程序在等待LSE就绪时卡死这通常意味着LSE没有起振或者起振条件不满足。排查链路先排除代码问题加超时保护后看程序是否还卡死用示波器抓LSE引脚波形确认晶振是否振荡检查晶振是否虚焊、是否型号不对查看数据手册确认需要的负载电容值用热风枪换电容再试6.4 现象四断电后重新上电读到的秒数“跳变”了这种情况偶尔在F1系列上遇到原因是上电后RTC寄存器和APB1时钟域不同步读取到了半更新的数据。解决方式是在读取前强制重新同步标准库函数是RTC_WaitForSynchro()它的本质是等待RTC的RSF寄存器同步标志置位。7. 进阶玩法把RTC和低功耗唤醒结合起来既然RTC已经接上了VBAT其实还可以顺手做一件很划算的事让设备在睡眠状态下定时醒来完成任务后继续睡。这对电池类产品特别有用。7.1 RTC闹钟中断和唤醒定时器以F1系列为例RTC除了秒中断还有闹钟中断。闹钟可以设置一个具体的时间到达后触发中断把MCU从停止模式Stop Mode或待机模式Standby Mode唤醒。如果使用待机模式唤醒后程序从头执行类似复位但备份域内容会保留。实际应用场景很典型一个环境监测传感器平时MCU进入Standby模式整机电流只有几个uA每10分钟RTC闹钟唤醒一次采集完数据、通过无线模块发送后再睡回去。这就把整个系统的平均功耗压得非常低。7.2 定时唤醒的时间戳精度问题使用RTC闹钟时有个细节闹钟寄存器的比较精度只能到秒级而且配置时间需要在秒计数变化时对齐。如果你配置10分钟后唤醒要注意“当前时间600秒”操作在秒计数刚好变化的瞬间写入可能导致匹配提前或延后1秒。稳妥的做法是先等待当前秒中断标志置位再写入“当前时间戳 600”。7.3 配合外部低速时钟校准时间之前提到LSE精度受限于晶振本身如果你对走时精度要求特别高比如每天误差低于0.5秒还可以考虑通过串口、NB-IoT或者Wi-Fi定期校时。具体做法是从网络获取标准时间戳计算当前RTC时间戳与标准时间戳的差值如果差值超过阈值直接调用RTC_SetCounter()重新设置如果差值不大可以通过软件微调RTC预分频器补偿这种方式在联网设备里非常实用既保证了断电保持又保证了长期精度。8. 最后的实操心得踩过这么多坑之后我对STM32的RTC掉电保持有几个自己的心得。首先是硬件优先级高于软件很多RTC问题查到最后都是硬件电路的问题——晶振不匹配、VBAT走线太长、电池座虚焊这些不是改代码能解决的。其次是备份寄存器标志位要尽早设计好不要等项目代码写完了再回头加不然初始化流程要动大手术。第三是上电初始化必须加超时保护产品在恶劣环境下的存活率比实验室里想象的要低得多。如果你是在现有项目里增加RTC功能我建议先只实现“时间戳保持”这个小功能验证硬件没问题后再扩展闹钟唤醒、备份寄存器存储设备状态等功能。还有一个我经常用的小技巧调试阶段在串口里打印备份寄存器的值能帮你快速判断“这次上电是首次初始化还是掉电恢复”这比猜要高效得多。希望这篇文章能帮你避掉大部分RTC的坑一次做通。
返回列表