STM32 RTC实时时钟\BKP备份寄存器\时间戳
一、Unix时间戳
想要计算当地北京时间,需要根据经度和闰年之类的运算得到(c语言里面可以调用time.h的函数)
二、UTC/GMT(科普)
三、时间戳转化
C语言的time.h模块提供了时间获取和时间戳转换的相关函数,可以方便的进行秒计数器、日期时间和字符串之间的转化
标红的三个最为重要
注:在STM32里面,因为没有系统时钟,所以time()函数用不了,描述转换为日期是默认使用local time()。但是需要提前预设时间数组。
解释:
time_t time(time_t*);//函数返回int64位的数据的函数,参数为指向time_t的指针
struct tm* gmtime(const time_t*);//函数返回一个指向 struct tm结构体的指针,参数是一个指向const time_t指针
1.time_t 实际上就是int 64类型,用来存储一直自增的秒数(现在是1748086069)
2.struct tm 是一个封装的结构体类型
成员分别为:秒、分钟、午夜开始的小时、一个月的几号、从一月开始的第几个月、从1900的第几年、从周末开始的星期几(0表示周日)、从1月1号开始的第几天、是否使用夏令时(+1使用,0不使用,-1表示不知道)
gmtime();函数运行
#include <stdio.h>
#include <time.h>time_t time_cnt; //time_t 表示int64类型的数据,用来存储一直自增的秒数
struct tm time_date;
char *time_str; int main(void){time_cnt=time(NULL); //获取当前时间返回到time_cnt里面 printf("%d\n",time_cnt);//打印time_cnt的值; time_date = *gmtime(&time_cnt);//由于gmtime的参数为指向time_t类型的指针 printf("%d\n",time_date.tm_year+1900);printf("%d\n",time_date.tm_mon+1);printf("%d\n",time_date.tm_mday);printf("%d\n",time_date.tm_hour);printf("%d\n",time_date.tm_min);printf("%d\n",time_date.tm_sec);printf("%d\n",time_date.tm_wday);return 0;
}
运行结果:
1748089398
2025
5
24
12
23
18
6
localtime();函数运行
#include <stdio.h>
#include <time.h>time_t time_cnt; //time_t 表示int64类型的数据,用来存储一直自增的秒数
struct tm time_date;
char *time_str; int main(void){time_cnt=time(NULL); //获取当前时间返回到time_cnt里面 printf("%d\n",time_cnt);//打印time_cnt的值; time_date = *localtime(&time_cnt);//由于gmtime的参数为指向time_t类型的指针 printf("%d\n",time_date.tm_year+1900);printf("%d\n",time_date.tm_mon+1);printf("%d\n",time_date.tm_mday);printf("%d\n",time_date.tm_hour);printf("%d\n",time_date.tm_min);printf("%d\n",time_date.tm_sec);printf("%d\n",time_date.tm_wday);return 0;
}
运行结果:
1748089571
2025
5
24
20
26
11
6
再附一张时间图 :
mktime();函数是一个逆过程。
3.char*,就是char型数据的指针,用来指向一个表示时间的字符串。
四、BKP简介
基本结构:
橙色部分为后备区,由VBAT供电,主电源有电时由主电源供电。BKP有四个寄存器,如上图。
五、RTC简介
- 首先配置RTCCLK时钟来源,从绿色部选一个。
- 之后通过预分频器对时钟进行分频。余数寄存器是一个自减计数器,存储当前的计数值;从中寄存器时技术目标,决定分频值。
- 之后配置32位计数器,可以进行日期时间的读写。
一些操作注意事项:
- 开启PWR和BKP的时钟、实验PWR使能BKP和RTC的访问
- 调用等待同步函数
- 调用一个等待的函数
六、代码部分
BKP代码:
void BKP_DeInit(void); //恢复缺损配置,手动清零
void BKP_TamperPinLevelConfig(uint16_t BKP_TamperPinLevel);//配置TAMPER侵入检测功能,引脚电平
void BKP_TamperPinCmd(FunctionalState NewState);//配置TAMPER侵入检测功能,使能
void BKP_ITConfig(FunctionalState NewState);//中断配置
void BKP_RTCOutputConfig(uint16_t BKP_RTCOutputSource);//时钟输出功能配置
void BKP_SetRTCCalibrationValue(uint8_t CalibrationValue);//设置RTC校准值
void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data);//bkp写备份寄存器
uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR);//读BKP备份寄存器
FlagStatus BKP_GetFlagStatus(void);
void BKP_ClearFlag(void);
ITStatus BKP_GetITStatus(void);
void BKP_ClearITPendingBit(void);
//BKP备份寄存器访问使能
void PWR_BackupAccessCmd(FunctionalState NewState);
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Buzzer.h"
#include "light sense.h"
#include "OLED.h"
int main(void)
{OLED_Init();RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);PWR_BackupAccessCmd(ENABLE);BKP_WriteBackupRegister(BKP_DR1,0x1234);OLED_ShowHexNum(1,1, BKP_ReadBackupRegister(BKP_DR1),4);while(1){}}
实验现象:将1234存放在BKP里面。在从里面读出来显示在OLED上面
RCC代码:
void RCC_LSEConfig(uint8_t RCC_LSE);//配置LSE外部低速时钟
void RCC_LSICmd(FunctionalState NewState);//配置LSI内部低速时钟
void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource);//选择RTCCLK时钟源
void RCC_RTCCLKCmd(FunctionalState NewState);//启动RTCCLK
FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG);//获取标志位,需要等待标志位LSERDY置1,时钟才算完成
RTC代码:
void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState);//配置中断输出
void RTC_EnterConfigMode(void);//进入配置模式,置CRL的CNF为1。
void RTC_ExitConfigMode(void);//退出配置模式,把CNF清零
uint32_t RTC_GetCounter(void);//获取CNT计数器的值
void RTC_SetCounter(uint32_t CounterValue);//写入CNT计数器的值
void RTC_SetPrescaler(uint32_t PrescalerValue);//写入预分频器,写入到PRL重装寄存器中
void RTC_SetAlarm(uint32_t AlarmValue);//写入闹钟值
uint32_t RTC_GetDivider(void);//读取预分频器中的DIV余数寄存器
void RTC_WaitForLastTask(void);//等待上次操作完成,循环直到RTOFF状态位为1
void RTC_WaitForSynchro(void);//等待同步,等待RSF置1
FlagStatus RTC_GetFlagStatus(uint16_t RTC_FLAG);
void RTC_ClearFlag(uint16_t RTC_FLAG);
ITStatus RTC_GetITStatus(uint16_t RTC_IT);
void RTC_ClearITPendingBit(uint16_t RTC_IT);
整体代码:
#include "stm32f10x.h" // Device header
#include <time.h>uint16_t MyRTC_Time[] = {2025, 5, 26, 18, 56, 55}; //定义全局的时间数组,数组内容分别为年、月、日、时、分、秒void MyRTC_SetTime(void); //函数声明/*** 函 数:RTC初始化* 参 数:无* 返 回 值:无 */
void MyRTC_Init(void)
{/*开启时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); //开启PWR的时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE); //开启BKP的时钟/*备份寄存器访问使能*/PWR_BackupAccessCmd(ENABLE); //使用PWR开启对备份寄存器的访问if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5) //通过写入备份寄存器的标志位,判断RTC是否是第一次配置//if成立则执行第一次的RTC配置{RCC_LSEConfig(RCC_LSE_ON); //开启LSE时钟while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) != SET); //等待LSE准备就绪RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //选择RTCCLK来源为LSERCC_RTCCLKCmd(ENABLE); //RTCCLK使能RTC_WaitForSynchro(); //等待同步RTC_WaitForLastTask(); //等待上一次操作完成RTC_SetPrescaler(32768 - 1); //设置RTC预分频器,预分频后的计数频率为1HzRTC_WaitForLastTask(); //等待上一次操作完成MyRTC_SetTime(); //设置时间,调用此函数,全局数组里时间值刷新到RTC硬件电路BKP_WriteBackupRegister(BKP_DR1, 0xA5A5); //在备份寄存器写入自己规定的标志位,用于判断RTC是不是第一次执行配置}else //RTC不是第一次配置{RTC_WaitForSynchro(); //等待同步RTC_WaitForLastTask(); //等待上一次操作完成}
}//如果LSE无法起振导致程序卡死在初始化函数中
//可将初始化函数替换为下述代码,使用LSI当作RTCCLK
//LSI无法由备用电源供电,故主电源掉电时,RTC走时会暂停
/*
void MyRTC_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);while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) != SET);RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);RCC_RTCCLKCmd(ENABLE);RTC_WaitForSynchro();RTC_WaitForLastTask();RTC_SetPrescaler(40000 - 1);RTC_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设置时间* 参 数:无* 返 回 值:无* 说 明:调用此函数后,全局数组里时间值将刷新到RTC硬件电路*/
void MyRTC_SetTime(void)
{time_t time_cnt; //定义秒计数器数据类型struct tm time_date; //定义日期时间数据类型time_date.tm_year = MyRTC_Time[0] - 1900; //将数组的时间赋值给日期时间结构体time_date.tm_mon = MyRTC_Time[1] - 1;time_date.tm_mday = MyRTC_Time[2];time_date.tm_hour = MyRTC_Time[3];time_date.tm_min = MyRTC_Time[4];time_date.tm_sec = MyRTC_Time[5];time_cnt = mktime(&time_date) - 8 * 60 * 60; //调用mktime函数,将日期时间转换为秒计数器格式//- 8 * 60 * 60为东八区的时区调整RTC_SetCounter(time_cnt); //将秒计数器写入到RTC的CNT中RTC_WaitForLastTask(); //等待上一次操作完成
}/*** 函 数:RTC读取时间* 参 数:无* 返 回 值:无* 说 明:调用此函数后,RTC硬件电路里时间值将刷新到全局数组*/
void MyRTC_ReadTime(void)
{time_t time_cnt; //定义秒计数器数据类型struct tm time_date; //定义日期时间数据类型time_cnt = RTC_GetCounter() + 8 * 60 * 60; //读取RTC的CNT,获取当前的秒计数器//+ 8 * 60 * 60为东八区的时区调整time_date = *localtime(&time_cnt); //使用localtime函数,将秒计数器转换为日期时间格式MyRTC_Time[0] = time_date.tm_year + 1900; //将日期时间结构体赋值给数组的时间MyRTC_Time[1] = time_date.tm_mon + 1;MyRTC_Time[2] = time_date.tm_mday;MyRTC_Time[3] = time_date.tm_hour;MyRTC_Time[4] = time_date.tm_min;MyRTC_Time[5] = time_date.tm_sec;
}
相关文章:

STM32 RTC实时时钟\BKP备份寄存器\时间戳
一、Unix时间戳 想要计算当地北京时间,需要根据经度和闰年之类的运算得到(c语言里面可以调用time.h的函数) 二、UTC/GMT(科普) 三、时间戳转化 C语言的time.h模块提供了时间获取和时间戳转换的相关函数,可以方便的进行秒计数器、…...
springcloud---gateway
目录标题 理解gateway代码示例filter与aop的联系ServerWebExchangeReactor 的 Context那是隐式传递Map吗Context和ThreadLocalSpring 的 AOP 是用的什么为什么过滤器要用异步非阻塞,而 AOP 用同步阻塞?理解gateway 代码示例 import io.netty.channel.Channel; import lombo…...

Axure设计案例——科技感立体柱状图
想让你的数据展示告别平淡无奇,成为吸引全场目光的焦点吗?快来瞧瞧这个Axure设计的科技感立体柱状图案例!科技感设计风格借助逼真的立体效果打破传统柱状图的平面感,营造出一种令人眼前一亮的视觉震撼。每一个柱状体都仿佛是真实存…...

app获取相册权限是否意味着所有相片都可随时读取?
针对安卓手机相册的隐私安全问题,我也比较好奇,App授予了相册权限,真的能自动读取用户的照片吗?最近做了一个小实验,我开发了2个小App,这2个App安装的时候只授予了相册权限,没有授予其他任何权限…...

2025年05月29日Github流行趋势
项目名称:agenticSeek 项目地址url:https://github.com/Fosowl/agenticSeek项目语言:Python历史star数:11898今日star数:2379项目维护者:Fosowl, steveh8758, klimentij, ganeshnikhil, apps/copilot-pull-…...

第十一节:第一部分:正则表达式:应用案例、爬取信息、搜索替换
正则表达式介绍 String提供的正则表达式的方法的书写规则 正则表达式总结 正则表达式作用: 作用三:搜索替换 案例分析及代码(图片解析) 代码: 代码一:校验手机号和邮箱格式是否正确 package com.itheima.…...
跟我学c++中级篇——动态库的资源处理
一、动态库的资源管理 动态库在编程中几乎是一个无法绕过的问题,不管是在哪个平台上都一样。在前面的文章中分析知道,编程的一个核心目标就是对计算机的资源进行管理和控制。动态库编程做为一个重要的技术,同样要面对资源的管理这个重要问题…...

新能源集群划分+电压调节!基于分布式能源集群划分的电压调节策略!
适用平台:MatlabYalmip Cplex (具体操作已在程序文件中说明) 参考文献:基于分布式能源集群化分的电压调节策略[D]. 一、文献解读 1. 主要内容/创新点 提出了一种基于分布式能源集群化的电压调节策略,计及分布式能源的有功、无功调节能力&a…...

端午安康 | 以匠心,致长远
端午节快乐 值此端午佳节,数图衷心感谢每一位合作伙伴与客户的信任相伴。 我们专注每一处细节,如粽米般紧密凝聚; 我们携手共进共赢,似龙舟竞渡般齐心协力。 未来,我们愿继续以创新为桨,与您共划时代新篇…...

漫画Android:事件分发的过程是怎样的?
当用户触摸屏幕时,硬件层会捕获触摸信号,并将其转化为内核事件。 Android系统会通过InputManagerService和WindowManagerService等服务将这些事件包装成MotionEvent对象,并将其传递给Activity的dispatchTouchEvent()方法中,Activi…...

2022 RoboCom 世界机器人开发者大赛-本科组(省赛)解题报告 | 珂学家
前言 题解 2022 RoboCom 世界机器人开发者大赛-本科组(省赛)。 感觉T5是最简单的,其他都不好做。 RC-u5 树与二分图 分值: 30分 思路: 容斥原理 树天然就是二分图,按深度d归类(偶数深度为S1,奇数深度为S2)&#x…...
什么是MCP技术,跟http技术有什么区别
什么是MCP技术? MCP(Model Context Protocol,模型上下文协议)是一种开源协议,旨在标准化大型语言模型(LLM)与外部数据源和工具之间的集成方式。 核心功能 上下文管理:保存对话历史…...

如何用ChatGPT提升学术长文质量
目录 一、关于让人工智能充当评审专家 二、关于分批次输入论文内容 三、来看看提示词 大家好这里是学术Anan,官网👉AIWritePaper~ 论文完成初稿之后,一般情况下,宝子们还需要找专家给我们提出评审意见。找专家评审其实并不容易…...

BKP(备份寄存器)和 RTC(实时时钟)
什么是BKP? 备份寄存器(BackupRegister)是42个16位的寄存器(不同设备存在差异:20字节(中容量和小容量)/84字节(大容量和互联型)),可用来存储 最多…...
springboot配置cors拦截器与cors解释
文章目录 cors?代码 cors? CORS(跨域资源共享)的核心机制是 由后端服务器(bbb.com)决定是否允许前端(aaa.com)的跨域请求 当浏览器访问 aaa.com 的页面,并向 bbb.com/list 发起请求时&#…...

【EdgeYOLO】《EdgeYOLO: An Edge-Real-Time Object Detector》
Liu S, Zha J, Sun J, et al. EdgeYOLO: An edge-real-time object detector[C]//2023 42nd Chinese Control Conference (CCC). IEEE, 2023: 7507-7512. CCC-2023 源码:https://github.com/LSH9832/edgeyolo 论文:https://arxiv.org/pdf/2302.07483 …...
Python打卡 DAY 38
知识点回顾: Dataset类的__getitem__和__len__方法(本质是python的特殊方法)Dataloader类minist手写数据集的了解 作业:了解下cifar数据集,尝试获取其中一张图片 import torch import torch.nn as nn import torch.opt…...

调试技巧总结
目录 一.调试1.什么是调试2.调试语义的分类2.1 静态语义2.2 动态语义 二.实用的调试技巧1.屏蔽代码2.借助打印3.查看汇编代码4.调试技巧总结 一.调试 1.什么是调试 调试,通俗易懂地说就是不断排查代码的错误,进行修正的过程,在写代码的时候…...

ubuntu安装blender并配置应用程序图标
ubuntu安装blender并配置应用程序图标 下载blender安装包解压缩并安装启动blender添加应用程序启动图标 下载blender安装包 blender中文服务站的下载网址 这里选择Linux 64位的Blender 4.2.4 LTS。下载速度很快。下载得到 解压缩并安装 将下载的压缩包放在/opt目录下&#…...

基于LBS的上门代厨APP开发全流程解析
上门做饭将会取代外卖行业成为新一轮的创业风口吗?杭州一位女士的3菜一汤88元套餐引爆社交网络,这个包含做饭、洗碗、收拾厨房的全套服务,正在重新定义"到家经济"的边界。当25岁的研究生系着围裙出现在客户厨房,当年轻姑…...

Redisson学习专栏(三):高级特性与实战(Spring/Spring Boot 集成,响应式编程,分布式服务,性能优化)
文章目录 前言一、Spring Boot深度整合实战1.1 分布式缓存管理1.2 声明式缓存1.3 响应式编程 二、分布式服务治理2.1 服务端实现2.2 客户端调用2.3 高级特性2.4 服务治理功能 三、分布式任务调度引擎四、连接池配置与网络参数调优4.1 连接池配置4.2 网络参数调优4.3 集群模式特…...

华为欧拉系统中部署FTP服务与Filestash应用:实现高效文件管理和共享
华为欧拉系统中部署FTP服务与Filestash应用:实现高效文件管理和共享 前言一、相关服务介绍1.1 Huawei Cloud EulerOS介绍1.2 Filestash介绍1.3 华为云Flexus应用服务器L实例介绍二、本次实践介绍2.1 本次实践介绍2.2 本次环境规划三、检查云服务器环境3.1 登录华为云3.2 SSH远…...

基于Docker和YARN的大数据环境部署实践最新版
基于Docker和YARN的大数据环境部署实践 目的 本操作手册旨在指导用户通过Docker容器技术,快速搭建一个完整的大数据环境。该环境包含以下核心组件: Hadoop HDFS/YARN(分布式存储与资源调度)Spark on YARN(分布式计算…...

【大模型】Bert
一、背景与起源 上下文建模的局限:在 BERT 之前,诸如 Word2Vec、GloVe 等词向量方法只能给出静态的词表示;而基于单向或浅层双向 LSTM/Transformer 的语言模型(如 OpenAI GPT)只能捕捉文本从左到右(或右到…...
《Go小技巧易错点100例》第三十四篇
本期分享: 1.sync.Mutex锁复制导致的异常 2.Go堆栈机制下容易导致的并发问题 sync.Mutex锁复制导致的异常 以下代码片段存在一个隐蔽的并发安全问题: type Counter struct {sync.MutexCount int }func foo(c Counter) {c.Lock()defer c.Unlock()…...
vue3+element-plus el-date-picker日期、年份筛选设置本周、本月、近3年等快捷筛选
一、页面代码: <template> <!-- 日期范围筛选框 --> <el-date-picker v-model"dateRange" value-format"YYYY-MM-DD" type"daterange" range-separator"至" start-placeholder"开始日期" end-…...
Vue 技术文档
一、引言 Vue 是一款用于构建用户界面的渐进式 JavaScript 框架,具有易上手、高性能、灵活等特点,能够帮助开发者快速开发出响应式的单页面应用。本技术文档旨在全面介绍 Vue 的相关技术知识,为开发人员提供参考和指导。 二、环境搭建 2.1…...

3 分钟学会使用 Puppeteer 将 HTML 转 PDF
需求背景 1、网页存档与文档管理 需要将网页内容长期保存或归档为PDF,确保内容不被篡改或丢失,适用于法律文档、合同、技术文档等场景。PDF格式便于存储和检索。 2、电子报告生成 动态生成的HTML内容(如数据分析报告、仪表盘)需导出为PDF供下载或打印。PDF保留排版和样…...

速通《Sklearn 与 TensorFlow 机器学习实用指南》
1.机器学习概览 1.1 什么是机器学习 机器学习是通过编程让计算机从数据中进行学习的科学。 1.2 为什么使用机器学习? 使用机器学习,是为了让计算机通过数据自动学习规律并进行预测或决策,无需显式编程规则。 1.3 机器学习系统的类型 1.…...

Ubuntu 下搭建ESP32 ESP-IDF开发环境,并在windows下用VSCode通过SSH登录Ubuntu开发ESP32应用
Ubuntu 下搭建ESP32 ESP-IDF开发环境,网上操作指南很多,本来一直也没有想过要写这么一篇文章。因为我其实不太习惯在linux下开发应用,平时更习惯windows的软件操作,只是因为windows下开发ESP32的应用编译时太慢,让人受…...