BKP 备份寄存器 RTC 实时时钟-stm32入门

news2024/12/29 7:47:12

这一章节我们要讲的主要内容是 RTC 实时时钟,对应手册,是第 16 章的位置。

实时时钟这个东西,本质上是一个定时器,但是这个定时器,是专门用来产生年月日时分秒,这种日期和时间信息的。所以学会了 STM32 的 RTC,你就可以在 STM32 内部拥有一个独立运行的钟表,想要记录或读取日期和时间,就可以通过操作 RTC 来实现。

那 RTC 这个外设呢,比较特殊,它和备份寄存器 BKP、电源控制 PWR 这两章的关联性比较强,在 RTC 这一章,BKP 和 PWR 也会经常来串门,所以我们这章节,就把 BKP 和 RTC 放在一起介绍,这样整体思路会比较清晰,PWR 电源控制,我们下章节再介绍。

然后,我们这一大章节,分三小节来介绍。第一小节,会单独介绍一下时间戳这个东西,这也是个蛮有意思的知识点。想要使用这款 STM32 的 RTC,学习时间戳的知识点还是非常必要的;第二小节,我们就学习 BKP 和 RTC 外设的结构;最后,第三小节,就是写代码,来完成程序现象了。这就是本章节的安排。

好,那先看一下我们最终的程序现象,本节一共有两个实例代码,12-1 读写备份寄存器,也就是读写 BKP;12-2 实时时钟,就是 OLED 显示年月日时分秒了。

先看一下第一个代码,这里,我们要在 STLINK 上再引出一根 3.3V 的电源,接到 VBAT 引脚,这根线就模拟一个电池的电源。一般情况下,VBAT 是电池供电口,需要接备用电池,但是我们目前套件里没有电池,所以就直接引出一根 3.3V 电源线来,也是一样的效果。那看一下显示屏,这个程序的目的是,在 BKP 备份寄存器写入两个数据,然后再把它们读出来,显示一下,目前 W 是写的内容,我们还没有写入数据,R 是读的内容,默认读出来都是 0。然后,我们可以按一下按钮,这时就在 2 个备份寄存器中,分别写入了 1234 5678,之后,读出来,也是 1234 5678,写入和读出是一样的,没问题。那继续按按键,我们会改变数据,再写入进去,下面读出来,和写入一样,都没问题。其实 BKP 备份寄存器和上一节学的 Flash 存储器类似,都是用来存储数据的,只是 Flash 的数据是真正的掉电不丢失,而 BKP 的数据,是需要 VBAT 引脚接上备用电池来维持的,只要 VBAT 有电池供电,即使 STM32 主电源断电,BKP 的值也可以维持原状。

那我们试一下,拔掉 STM32 板子最下面这个主电源的正极引脚,现在 STM32 断电,但是 VBAT 有电,可以维持 BKP 的数据,再次上电后,在没有写数据的情况下,直接读出 BKP,它的数据和断电之前是一样的,这说明 BKP 的数据在主电源断电后,得到了保持,并且在系统复位后,可以按下复位键,BKP 的数据也不会复位,那如果我们把 VBAT 的电池断电,再次拔掉主电源,重新上电,BKP 的数据就清零了,因为 BKP 本质上,并不能完全掉电不丢失,它的数据,需要 VBAT 引脚提供备用电池来维持,这就是 BKP 备份寄存器的特性。如果你的 STM32 接了备用电池,那 BKP 可以完成一些主电源掉电时,保存少量数据的任务,这就是第一个代码的现象。

其实备份寄存器和 VBAT 引脚的存在,更多的是为了服务 RTC 的,所以我们接着看第二个代码,实时时钟。这就是实时时钟的现象,第一行是日期,目前是给的一个测试时间,2023 年 1 月 2 日,第二行是时间,目前是 0 时 0 分 xx 秒,第三行是时间戳的秒计数器,目前是 16 亿多,这个什么意思,等会儿就来学习。第四行是 RTC 预分频器的计数值,这个先看一下就行,用途我们写代码的时候再研究,这就是我们这个实时时钟的显示。

当然实时时钟,光有显示还不够,为了保证时间不出错,他还要有其他特性。首先是复位,既然你在计时,总不能每次复位都重新设置时间吧,我们按下复位键,可以看到,时间会继续运行,不会复位。然后,实时时钟,在系统主电源断电后,它还需要继续运行,就像我们手机一样,关机后,里面的时钟还必须要继续走,要不然时间就错了,是吧,所以只要在 VBAT 接上了备用电源,我们再断开系统主电源,然后插上,可以看到时间数据不会丢失,并且,在主电源断开的时间里,RTC 会继续走时,不会因为主电源断电而暂停,这就是 RTC 实时时钟的程序现象。可以发现,RTC 这个复位和主电源掉电后,数据不丢失,就是借用 BKP 来实现的,所以 RTC 和 BKP 关联程度是比较高的,这就是实时时钟的程序现象。

另外在这里,还要提几个在测试程序的时候,遇到的硬件 bug。
首先是,有的芯片,我给主电源断电后,VBAT 的电源还会给微弱地整个系统供电,这导致我主电源拔掉后,电源指示灯和 OLED 屏幕还会微弱的亮着,这是一个问题,当然这个问题其实也不影响最终的实验现象。
然后是还有的芯片,在进行 RTC 实验时,会出现 RTC 晶振不起振的情况,这会导致程序卡死在等待晶振起振的地方,这个问题还没找到完美的解决方法。但是在学习过程中,也是可以有一些替代方法可以使用的,所以这些问题先给大家提个醒,替代方法,我们后续写代码的时候再说。

好,那程序现象我们就看到这里。

1. Unix 时间戳

在这一小节,我将会介绍,时间戳是什么东西,为什么要使用时间戳来计时。然后 UTC 和 GMT 是什么东西,这一块就是一些科普性质的知识点。然后就是时间戳里的秒计数器和日期时间数据如何互相转换,这涉及到 C 语言中的 time.h 这个官方函数库。这里我会在 DevC++ 这个软件里,一一调用这些函数,来给大家演示它们的用法。

所以我们本小节的任务有两个。

  1. 了解时间戳,它到底是什么东西。
  2. 会使用 C 语言 time.h 里面的这些函数进行时间戳各种形式数据的转换。

那本小节的内容,其实是计算机领域的一个通用知识点,不特别应用在 STM32 中,所以学完本小节,你之后在其他地方,说不定也能用得到。好,那我们来看一下

1.1 Unix 时间戳简介

Unix 时间戳最早是在 Unix 系统使用的,所以叫 Unix 时间戳。之后很多由 Unix 演变而来的系统,也都继承了 Unix 时间戳的规定。目前 Linux、Windows、安卓这些系统它们底层的计时系统,都是使用的 Unix 时间戳。所以在我们现在计算机世界的底层,Unix 时间戳还是在扮演着重要的角色的。

  1. Unix 时间戳(Unix Timestamp),它的定义是从 UTC/GMT 的 1970 年 1 月 1 日 0 时 0 分 0 秒开始所经过的秒数,不考虑闰秒。

这里大家可能有些疑问:
第一,UTC/GMT,这个是什么东西。
第二,闰年、闰月,这些我们听得比较多,但是这个闰秒,是个什么东西呢。
这两个知识点,我们等会儿再介绍。
现在这句话,我们简单理解一下,意思就是,时间戳是一个计数器数值,这个数值表示的是一个从 1970 年 1 月 1 日 0 时 0 分 0 秒开始,到现在,总共所经过的秒数,所以时间戳这个计时系统,和我们常用的年月日时分秒这个计时系统有很大差别。年月日时分秒计时系统是每 60 秒,进位一次,记为 1 分钟,每 60 分钟进位 一次,记为 1 小时,之后继续进位,就是日、月、年了。而时间戳计时系统就比较简单粗暴了,它定义 1970 年 1 月 1 日 0 时整为 0 秒,之后,就只用最基本的秒来计时,永不进位,60s 就是 60s,100s 就是 100s,一千秒、一万秒、一亿秒,无论这个数有多大,我都不进位,始终都只用秒来计时。所以从 1970 年计到现在,这个时间戳的秒数已经非常大了,目前这个秒数,已经来到了 16 亿这个数量级了。对于人类来说,这个 16 亿秒,肯定是又难记又难理解;但是对于计算机来说,一个永不进位的秒,无论是存储,还是计算,都是非常方便的。所以时间戳在计算机程序的底层,应用非常广泛,时间戳的秒计数器和日期时间,可以互相转换,在计算器的底层,我们使用秒计数器来计时,需要给人类观看时,我们就转换为年月日时分秒这样的格式就行了。
那使用这样一个很大的秒数来表示时间,有很多好处。
第一,就是简化硬件电路,我们在设计 RTC 硬件电路的时候,直接弄一个很大的秒寄存器就行了,不需要再考虑什么年月日寄存器、进位,大月小月、平年闰年这些东西了。对于硬件电路设计来说,是非常友好的。
第二,就是在进行一些时间间隔的计算时,非常方便。比如 1 月 1 号 8 点到 3 月 1 号 18 点之间间隔了多少小时啊?这个如果用年月日时分秒来计算的话,需要考虑的东西就比较多了。但如果用秒计数器来算的话,我们只需要把两个时刻的秒数相减,再除一个小时的秒数,就可以很快计算两个时刻的间隔了。
第三,就是存储方便,存储秒数,一个比较大的变量就行了,存储年月日时分秒的话,就得很多变量了。
那当然使用秒计数器来表示时间,也有坏处。
就是比较占用软件资源,在每次进行秒计数器和日期时间转换时,软件都要进行一通比较复杂的计算,这会占用一些软件资源,那这就是使用时间戳的一些好处和坏处。

时间戳存储在一个秒计数器中,秒计数器为32位/64位的整型变量

那计算机为了存储这样一个永不进位的秒数,这个数据变量类型还是要定义大一些,对吧,这个变量类型,在不同系统中,定义是不一样的。在早期的 Unix 系统中,这个秒数大多是用 32 位有符号的整形变量来存储的。32 位有符号数,所能表示的最大数字是 232/2 - 1 = 21 亿多,这其实是有溢出风险的,因为目前到 2023 年,时间戳已经计到 16 亿了,再过一些年,32 位有符号数,就存不下这么大的数字了。那根据计算,32 位有符号数的时间戳会在 2038 年的 1 月 19 号溢出,到时候,采用 32 位有符号数存储时间戳的设备,计时系统就会因为数据溢出而出错,这可能会导致很多不健全的计算机程序崩溃,这就是 2038 年危机,大家感兴趣的话可以网上搜一搜。那当然,随着操作系统和设备的更新换代,目前的手机电脑等设备,基本上都已经采用 64 位的数据来存储时间戳了,64 位的时间戳,能存储的时间范围非常非常的大,总之,对于人类来说,完全可以高枕无忧了。最后我们本节 STM32 中的 RTC,可以看一下手册,可以看到,它核心的计时部分是一个 32 位的可编程计数器,这说明我们这款 STM32,它的时间戳是 32 位的数据类型,32 位的时间戳,这表示我们这个 STM32 也会在 2038 年出现 bug 吗?实际上并不会,因为根据研究,这个时间戳在 STM32 程序中定义的其实是无符号的 32 位,无符号 32 位最大数值是 232 - 1,计算一下,要到 2106 年才会溢出,虽然不是高枕无忧,但是有生之年,八成是不用担心。好,这就是时间戳的存储格式和溢出风险的分析。

世界上所有时区的秒计数器相同,不同时区通过添加偏移来得到当地时间

我们知道,地球上不同经度,它的时间是不一样的,穿过英国伦敦的经线,我们把它叫做本初子午线,这个位置的时间是一个时间标准。我们时间戳所说的 1970 年 1 月 1 日 0 时 0 分 0 秒,也是指的伦敦时间的 0 时 0 分 0 秒。那其他地方呢,可以分为 24 个时区,每偏差一个时区,时间就要加或减一个小时,我们处理不同时区的方式是所有时区共用一个时间戳的秒计数器,也就是在伦敦秒计数器是 0,在北京也是 0,然后根据不同时区,我们再添加小时的偏移即可。比如秒计数器的 0 对应伦敦时间的 0 点,那中国,使用北京时间,处于东 8 区的位置,对应北京的时间,就是 8 点。这就是时间戳对不同时区的处理方式。

那最后看一下下面这个图,总结一下上面的知识点。
在这里插入图片描述
图中这个箭头,代表的是一个时间轴。在这个时间轴上,我们要定义一个起点,时间戳从这个起点开始计时,这个起点是人为规定的,当时的设计者选择了伦敦时间的 1970 年 1 月 1 日 0 点。

对于 1970 年之前的时间,时间戳是无法表示的,那时间戳有两种表现形式。
一种是它的基本形式,也就是永不进位的秒计数器,从 0 开始,一直往后,每过 1s,加一个数;
另一种就是秒计数器经过计算,翻译出来的日期和时间了,比如 0s,对应伦敦时间 1970 年 1 月 1 日 0 点,然后秒计数器一直计啊计,比如计到这个 10 亿秒的时候,就对应伦敦时间 2001 年 9 月 9 日 1 时 46 分 40 秒。

那我咋知道 10 亿秒对应这个日期的时间呢?这背后要经过一些比较复杂的计算。比如先算一年有多少秒,得到现在是哪一年,然后再算一天有多少秒,得到现在是一年的第几天,然后再计算现在是几月几号,最后再计算是几时几分几秒。这里面还需要考虑大月小月、平年闰年这些特殊情况。
所以可以想到,这个计算是非常麻烦的,但是好在,这个计算步骤是固定的。而且,C 语言官方已经帮我们把程序写好了,这就是我们等会要学的 time.h 这个模块。这里面就有现成的,秒计数器转换日期时间,日期时间转换秒计数器这些函数。所以这里,我们只要会调用 time.h 的函数,就可以知道这些秒计数器和日期时间的对应关系了。至于计算步骤,我们不用过多了解,感兴趣的话可以自行研究。那有了 time.h 里的函数,这个秒计数器的计算,就非常简单了。比如 1672588795 这个秒数调用函数一计算对应的伦敦时间就是 2023 年 1 月 1 日 15 点 59 分 55 秒,那最后一行,在伦敦时间的基础上,得到北京时间,就比较简单了,每个秒计数器对应的伦敦时间,再加上 8 个小时就是对应的北京时间,这就是这个 Unix 时间戳整个的设计思路。

最后可以给大家推荐一个网站工具,比如在百度直接搜索 Unix 时间戳,然后就可以看到很多时间戳在线转换工具,我们打开网站,里面就有别人做好的转换工具。比如显示的是现在这个时刻对应的秒计数器,就是这么多秒;然后时间戳,就是秒计数器,你输入多少秒,点转换,它就能告诉你,对应的北京时间是多少;然后你输入一个日期时间,点转换,它就能告诉你对应的秒计数器是多少。当然这里好像只能转换北京时间,比如给个 0s,因为是北京时间,它对应的就是 8 点,这个我们也应该清楚是怎么回事,这就是这个时间戳在线工具。大家写代码的时候,可以参考这个工具来进行验证,这个了解一下。

好,时间戳的基础知识我们就了解这么多。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1316763.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java系列-ConcurrentHashMap-addCount

1.addCount public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>implements ConcurrentMap<K,V>, Serializable {private final void addCount(long x, int check) {CounterCell[] as; long b, s;//1.counterCells不为null//2.或者 x加到baseCou…

挑战52天学小猪佩奇笔记--day24

52天学完小猪佩奇--day24 ​【本文说明】 本文内容来源于对B站UP 脑洞部长 的系列视频 挑战52天背完小猪佩奇----day24 的视频内容总结&#xff0c;方便复习。强烈建议大家去关注一波UP&#xff0c;配合UP视频学习。 注&#xff1a;这集开始变成一段一段的猜台词&#xff0c;加…

网站提示“不安全”

当你在浏览网站时&#xff0c;有时可能会遇到浏览器提示网站不安全的情况。这通常是由于网站缺乏SSL证书所致。那么&#xff0c;从SSL证书的角度出发&#xff0c;我们应该如何解决这个问题呢&#xff1f; 首先&#xff0c;让我们简单了解一下SSL证书。SSL证书是一种用于保护网站…

pybind11:对比C++和Python解线性方程组的速度

前言 上篇博客介绍了如何在用pybind11实现ndarray和C数组的转换自由&#xff0c;pybind11&#xff1a;实现ndarray转C原生数组&#xff08;没看过的朋友可以去看一看&#xff09;下面我们以一个实际的算法例子演示一下如何使用这个技术&#xff0c;方便的实现 Python 调用 C 写…

Java架构师系统架构高可用维度分析

目录 1 导语2 可用性介绍3 本地高可用-集群、分布式4 本地高可用-数据逻辑保护5 异地容灾-双活、两地三中心6 异地容灾-DRP规划&BCP业务连续性7 多活和妥协方案8 高可用流程9 总结想学习架构师构建流程请跳转:Java架构师系统架构设计 1 导语 Java架构师在进行系统架构设…

蓝桥杯专题-真题版含答案-【排序法 - 改良的选择排序】【插补搜寻法】【稀疏矩阵】【欧拉与鸡蛋】

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

【golang/g3n】3D游戏引擎G3N的windows安装与测试

目录 说在前面安装测试 说在前面 操作系统&#xff1a;win 11go version&#xff1a;go1.21.5 windows/amd64g3n版本&#xff1a;github.com/g3n/engine v0.2.0其他&#xff1a;找了下golang 3d相关的库&#xff0c;目前好像就这个比较活跃 安装 按照官方教程所说&#xff0c;…

ES6 面试题 | 13.精选 ES6 面试题

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

IDEA中alt enter不显示创建实现类快捷键

alt enter不显示创建实现类快捷键是因为idea中的设置没打开&#xff0c;按照一下设置打开就可以了。 点击setting-->>editor-->>intentions-->>java下的declaration 如下图所示&#xff1a;

PXI/PCIe/VPX机箱 ARM|x86 + FPGA测试测量板卡解决方案

PXI便携式测控系统是一种基于PXI总线的便携式测试测控系统&#xff0c;它填补了现有台式及机架式仪器在外场测控和便携测控应用上的空白&#xff0c;在军工国防、航空航天、兵器电子、船舶舰载等各个领域的外场测控场合和科学试验研究场合都有广泛的应用。由于PXI便携式测控系统…

HiveSql语法优化一 :分组聚合优化

Hive中未经优化的分组聚合&#xff0c;是通过一个MapReduce Job实现的。Map端负责读取数据&#xff0c;并按照分组字段分区&#xff0c;通过Shuffle&#xff0c;将数据发往Reduce端&#xff0c;各组数据在Reduce端完成最终的聚合运算。 Hive对分组聚合的优化主要围绕着减少Shuf…

Linux 基本语句_15_Tcp并发服务器

原理&#xff1a; 利用父子进程。父进程接收客户端的连接请求&#xff0c;子进程处理客户端的数据处理操作&#xff0c;两者各施其职。最终实现能够多个客户端连接一个服务端的操作。 代码&#xff1a; 服务端代码&#xff1a; #include <stdio.h> #include <sys/…

时序预测 | Python实现LSTM-Attention-XGBoost组合模型电力需求预测

时序预测 | Python实现LSTM-Attention-XGBoost组合模型电力需求预测 目录 时序预测 | Python实现LSTM-Attention-XGBoost组合模型电力需求预测预测效果基本描述程序设计参考资料预测效果 基本描述 该数据集因其每小时的用电量数据以及 TSO 对消耗和定价的相应预测而值得注意,从…

Eslint 要被 Oxlint替换了吗

什么是 Oxlint 由于最近的rust在前端领域的崛起,基于rust的前端生态链遭到rust底层重构,最近又爆出OxLint,是一款基于Rust的linter工具。Oxlint在国外前端圈引起热烈讨论,很多大佬给出了高度评价。 事实上,Oxlint 是 Oxc 项目旗下的一款产品,专为 JavaScript 和 TypeSc…

SLAM算法与工程实践——SLAM基本库的安装与使用(5):Ceres优化库

SLAM算法与工程实践系列文章 下面是SLAM算法与工程实践系列文章的总链接&#xff0c;本人发表这个系列的文章链接均收录于此 SLAM算法与工程实践系列文章链接 下面是专栏地址&#xff1a; SLAM算法与工程实践系列专栏 文章目录 SLAM算法与工程实践系列文章SLAM算法与工程实践…

【️接口和抽象类的区别,如何选择?】

✅接口和抽象类的区别&#xff0c;如何选择&#xff1f; ✅ 接口和抽象类的区别✅方法定义✅修饰符✅构造器✅继承和实现✅单继承 、 多实现✅职责不同 ✅什么是模板方法模式&#xff0c;有哪些应用呢&#xff1f;✅典型理解✅示例&#x1f4a1;思考 ✅你在工作中是如何使用设计…

Swin-Transformer 在图像识别中的应用

1. 卷积神经网络简单介绍 图像识别任务主要利用神经网络对图像进行特征提取&#xff0c;最后通过全连接层将特征和分类个数进行映射。传统的网络是利用线性网络对图像进行分类&#xff0c;然而图像信息是二维的&#xff0c;一般来说&#xff0c;图像像素点和周围邻域像素点相关…

【MISRA C 2012】Rule 5.4 宏标识符应该是不同的

1. 规则1.1 原文1.2 分类 2. 关键描述3. Example4. 代码实例 1. 规则 1.1 原文 1.2 分类 规则5.4&#xff1a;宏标识符应该是不同的 Required要求类规范。 2. 关键描述 该规则要求&#xff0c;当定义宏时&#xff0c;其名称与: •当前定义的其他宏的名称;和 •参数的名称。…

网线市场现状与发展趋势预测

随着物联网、5G、云计算等技术的迅速发展&#xff0c;全球对于高速、稳定的网络需求急剧增长&#xff0c;这进一步推动了网线市场的发展。各种网络应用场景&#xff0c;从家庭到企业、数据中心到智能城市&#xff0c;都需要大量的高质量网线来支持数据传输和通信需求。本文将对…

windows 10 安装和配置nginx

1 下载nginx 1.1 下载地址&#xff1a;http://nginx.org/en/download.html 1.2 使用解压到安装目录 1.3 更改配置 conf目录下nginx.conf 修改为未被占用的端口&#xff0c;地址改成你的地址 server {listen 9999;server_name localhost;#charset koi8-r;#access_lo…