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

BKP(备份寄存器)和 RTC(实时时钟)

什么是BKP?

        备份寄存器(BackupRegister)42个16位的寄存器(不同设备存在差异:20字节(中容量和小容量)/84字节(大容量和互联型)),可用来存储 最多84个字节的用户应用程序数据。他们处在备份域里。(VDD电 源被切断,他们仍然由VBAT维持供电。

特点:

  • 系统待机模式下被唤醒,或系统复位或电源复位时,他们也不会被复位
  • 当断电后,后备寄存器中写入的数据会丢失

作用:

 管理侵入检测 和 RTC校准功能

        复位后,备份寄存器 和 RTC的访问 被禁止,并且 备份域 被保护以防止可能存在的意外的写操作。执行以下操作可以使能对备份寄存器和RTC的访问

  • 通过设置寄存器RCC_APB1ENR的 PWREN 和 BKPEN 位来 打开电源 和 后备接口的时钟
  • 电源控制寄存器(PWR_CR)的 DBP位 来使能对 后备寄存器和 RTC的访问。

BKP框图 

小实验:读写BKP后备寄存器 

bkp.c文件代码:

#include "rtc.h"RTC_HandleTypeDef rtc_handle = {0};
void rtc_init(void){//要想读写BKP  //1.要开始电源和后背寄存器的时钟__HAL_RCC_PWR_CLK_ENABLE();   __HAL_RCC_BKP_CLK_ENABLE();//使能后备寄存器HAL_PWR_EnableBkUpAccess();rtc_handle.Instance = RTC;rtc_handle.Init.AsynchPrediv = 32767;rtc_handle.Init.OutPut = RTC_OUTPUTSOURCE_NONE;    HAL_RTC_Init(&rtc_handle);
}/*读后备寄存器中的数据,并返回*/
uint16_t rtc_read_bkr(uint8_t bkrx){uint32_t data = 0;data = HAL_RTCEx_BKUPRead(&rtc_handle, bkrx);return (uint16_t)data;
}/*对后备寄存器中写数据,指定参数:哪个寄存器,写入的数据*/
void rtc_write_bkr(uint8_t bkrx,uint16_t data){HAL_RTCEx_BKUPWrite(&rtc_handle,bkrx,data);
}
  • bkp.h文件代码
#ifndef __RTC_H__
#define __RTC_H__
#include "stm32f1xx.h"void rtc_init(void);
uint16_t rtc_read_bkr(uint8_t bkrx);
void rtc_write_bkr(uint8_t bkrx,uint16_t data);#endif
  •  mian.c文件代码
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "uart1.h"
#include "rtc.h"int main(void)
{HAL_Init();                         /* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */led_init();                         /* LED初始化 */uart1_init(115200);printf("hello,world\r\n");rtc_init();rtc_write_bkr(1,0xABCD);printf("读出来的十六进制的数是:%X\r\n",rtc_read_bkr(1));while(1){ }
}

实验现象:

  • 现象1:当系统复位后,之前写入的的数据依旧被打印出来。
  • 现象2:断电后,后备寄存器中的数据会丢失。 

什么是RTC? 

        实时时钟是一个独立的定时器。 RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟 和 日历的功能(F1芯片是没有这个功能的)。修改计数器的值可以重新设置系统当前的时间和日期。

和上面的BKP原理相同:        

        RTC模块 和 时钟配置系统 (RCC_BDCR寄存器处于后备区域,即在系统复位或从待机模式唤醒后, RTC的设置和时间维持不变。

        复位后,对备份寄存器和RTC的访问被禁止,并且备份域被保护以防止可能存在的意外的写操作。执行以下操作可以使能对备份寄存器和RTC的访问:

  • 通过设置寄存器RCC_APB1ENRPWRENBKPEN位来 打开电源 和 后备接口 的时钟
  • 电源控制寄存器(PWR_CR)DBP位来使能对 后备寄存器和 RTC的访问。

RTC框图 

 简图:

可选择三种RTC时钟源:

  • HSE时钟除以128(通常为8MHz/128
  • LSE振荡器时钟(通常为32.768KHz
  • LSI振荡器时钟(40KHz

32位的可编程计数器(CNT),可对应Unix时间戳的秒计数器。

Unix时间戳(格林威治 -- 北京时间)是从197011日的 00:00:00(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒。

20位的可编程预分频器,可适配不同频率的输入时钟。

(参考手册)图: 

RTC寄存器 

  • 备份域控制寄存器 (RCC_BDCR)

  • RTC控制寄存器高位(RTC_CRH) 

  • RTC控制寄存器低位(RTC_CRL) 

  •  RTC预分频装载寄存器(RTC_PRLH/RTC_PRLL) 

  • RTC预分频器余数寄存器(RTC_DIVH / RTC_DIVL) 

RTC库函数 

  • 获取时间、日期、闹钟的函数: 

  •  设置时间、日期、闹钟的函数:

  • 获取 RTC控制寄存器中的RTOFF位是否置1:可以进行写操作

RTC驱动步骤

 小实验1:读写RTC时间实验

实验目的

配置RTC来实现,设置时钟和日期 

硬件清单

 stm32f103c8t6、USB转TTL、ST-Link

实验代码 

  • rtc.c文件代码:
#include "rtc.h"
#include "stdio.h"RTC_HandleTypeDef rtc_handle = {0};void rtc_init(void){//要想读写BKP  //1.要开始电源和后背寄存器的时钟__HAL_RCC_PWR_CLK_ENABLE();   __HAL_RCC_BKP_CLK_ENABLE();//使能后备寄存器HAL_PWR_EnableBkUpAccess();rtc_handle.Instance = RTC;rtc_handle.Init.AsynchPrediv = 32767;rtc_handle.Init.OutPut = RTC_OUTPUTSOURCE_NONE;    HAL_RTC_Init(&rtc_handle);
}void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc){if(hrtc->Instance == RTC){__HAL_RCC_RTC_ENABLE();//配置外部时钟源(3种):LSE,HSE,LSIRCC_OscInitTypeDef osc_initstruct = {0};osc_initstruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;osc_initstruct.LSEState = RCC_LSE_ON;osc_initstruct.PLL.PLLState = RCC_PLL_NONE;HAL_RCC_OscConfig(&osc_initstruct);//配置RTC选择的外部时钟源RCC_PeriphCLKInitTypeDef periph_initstruct = {0};periph_initstruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;periph_initstruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;HAL_RCCEx_PeriphCLKConfig(&periph_initstruct);HAL_NVIC_SetPriority(RTC_Alarm_IRQn,2,2);HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);}
}/*读后备寄存器中的数据,并返回*/
uint16_t rtc_read_bkr(uint8_t bkrx){uint32_t data = 0;data = HAL_RTCEx_BKUPRead(&rtc_handle, bkrx);return (uint16_t)data;
}/*对后备寄存器中写数据,指定参数:哪个寄存器,写入的数据*/
void rtc_write_bkr(uint8_t bkrx,uint16_t data){HAL_RTCEx_BKUPWrite(&rtc_handle,bkrx,data);
}/*获取时间的函数*/
void rtc_get_time(void){RTC_TimeTypeDef rtc_time = {0};RTC_DateTypeDef rtc_date = {0};HAL_RTC_GetTime(&rtc_handle,&rtc_time,RTC_FORMAT_BIN);HAL_RTC_GetDate(&rtc_handle,&rtc_date,RTC_FORMAT_BIN);printf("rtc time: %d-%02d-%02d;%02d:%02d:%02d\r\n",rtc_date.Year + 2000,rtc_date.Month,rtc_date.Date,rtc_time.Hours,rtc_time.Minutes,rtc_time.Seconds);
}/*设置时间的函数*/
void rtc_set_time(struct tm time_data){RTC_TimeTypeDef rtc_time = {0};RTC_DateTypeDef rtc_date = {0};rtc_time.Hours = time_data.tm_hour;rtc_time.Minutes = time_data.tm_min;rtc_time.Seconds = time_data.tm_sec;HAL_RTC_SetTime(&rtc_handle,&rtc_time,RTC_FORMAT_BIN);rtc_date.Year = time_data.tm_year - 2000;rtc_date.Month = time_data.tm_mon;rtc_date.Date = time_data.tm_mday;HAL_RTC_SetDate(&rtc_handle,&rtc_date,RTC_FORMAT_BIN);while(!__HAL_RTC_ALARM_GET_FLAG(&rtc_handle,RTC_FLAG_RTOFF));
}

注意事项: 在MspInit()函数中,初始化:三个时钟源和RTC的时钟源:

  •  HAL_RCC_OscConfig( ); //三个时钟源的选择
  •  HAL_RCCEx_PeriphCLKConfig( ); //RTC时钟源的选择

在设置时间的函数中,要判断RCC控制寄存器中的RTOFF的标志位是否置1:可以读写。

上面代码的意思是:若RTOFF位没有置1,进行等待。

  • rtc.h文件代码:
#ifndef __RTC_H__
#define __RTC_H__
#include "stm32f1xx.h"
#include "time.h"void rtc_init(void);
uint16_t rtc_read_bkr(uint8_t bkrx);
void rtc_write_bkr(uint8_t bkrx,uint16_t data);void rtc_get_time(void);
void rtc_set_time(struct tm time_data);
void rtc_set_alarm(struct tm time_date);
#endif
  • mian.c文件代码
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "uart1.h"
#include "rtc.h"int main(void)
{HAL_Init();                         /* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */led_init();                         /* LED初始化 */uart1_init(115200);printf("hello,world\r\n");rtc_init();if(rtc_read_bkr(1) != 0xABED){rtc_write_bkr(1,0xABED);printf("读出来的十六进制的数是:%X\r\n",rtc_read_bkr(1));struct tm time_data;time_data.tm_year = 2025;time_data.tm_mon = 5;time_data.tm_mday = 30;time_data.tm_hour = 11;time_data.tm_min  = 31;time_data.tm_sec = 0;rtc_set_time(time_data);  }while(1){ rtc_get_time();delay_ms(1000);}
}

总结:要复习函数中的形参传入结构体知识点。 

小实验2:RTC闹钟实验

     实验目的

     设置闹钟

    实验代码

    • MspInit()函数中添加:

    •  中断服务函数

    •  设置闹钟的实验

    •  rtc.h文件代码
    #ifndef __RTC_H__
    #define __RTC_H__
    #include "stm32f1xx.h"
    #include "time.h"void rtc_init(void);
    uint16_t rtc_read_bkr(uint8_t bkrx);
    void rtc_write_bkr(uint8_t bkrx,uint16_t data);void rtc_get_time(void);
    void rtc_set_time(struct tm time_data);
    void rtc_set_alarm(struct tm time_date);
    #endif
    • mian.c文件代码 
    #include "sys.h"
    #include "led.h"
    #include "delay.h"
    #include "uart1.h"
    #include "rtc.h"int main(void)
    {HAL_Init();                         /* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */led_init();                         /* LED初始化 */uart1_init(115200);printf("hello,world\r\n");rtc_init();if(rtc_read_bkr(1) != 0xABED){rtc_write_bkr(1,0xABED);printf("读出来的十六进制的数是:%X\r\n",rtc_read_bkr(1));struct tm time_data;time_data.tm_year = 2025;time_data.tm_mon = 5;time_data.tm_mday = 30;time_data.tm_hour = 11;time_data.tm_min  = 31;time_data.tm_sec = 0;rtc_set_time(time_data);  struct tm alarm_date;alarm_date.tm_hour = 11;alarm_date.tm_min = 31;alarm_date.tm_sec = 20;rtc_set_alarm(alarm_date);}while(1){ rtc_get_time();delay_ms(1000);}
    }

    相关文章:

    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年等快捷筛选

    一、页面代码&#xff1a; <template> <!-- 日期范围筛选框 --> <el-date-picker v-model"dateRange" value-format"YYYY-MM-DD" type"daterange" range-separator"至" start-placeholder"开始日期" end-…...

    Vue 技术文档

    一、引言 Vue 是一款用于构建用户界面的渐进式 JavaScript 框架&#xff0c;具有易上手、高性能、灵活等特点&#xff0c;能够帮助开发者快速开发出响应式的单页面应用。本技术文档旨在全面介绍 Vue 的相关技术知识&#xff0c;为开发人员提供参考和指导。 二、环境搭建 2.1…...

    3 分钟学会使用 Puppeteer 将 HTML 转 PDF

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

    速通《Sklearn 与 TensorFlow 机器学习实用指南》

    1.机器学习概览 1.1 什么是机器学习 机器学习是通过编程让计算机从数据中进行学习的科学。 1.2 为什么使用机器学习&#xff1f; 使用机器学习&#xff0c;是为了让计算机通过数据自动学习规律并进行预测或决策&#xff0c;无需显式编程规则。 1.3 机器学习系统的类型 1.…...

    Ubuntu 下搭建ESP32 ESP-IDF开发环境,并在windows下用VSCode通过SSH登录Ubuntu开发ESP32应用

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

    [FreeRTOS- 野火] - - - 临界段

    一、介绍 临界段最常出现在对一些全局变量进行操作的场景。 1.1 临界段的定义 临界段是指在多任务系统中&#xff0c;一段需要独占访问共享资源的代码。在这段代码执行期间&#xff0c;必须确保没有任何其他任务或中断可以访问或修改相同的共享资源。 临界段的主要目的是防…...

    【洛谷P9303题解】AC代码- [CCC 2023 J5] CCC Word Hunt

    在CCC单词搜索游戏中&#xff0c;单词可以隐藏在字母网格中&#xff0c;以直线或直角的方式排列。以下是对代码的详细注释和解题思路的总结&#xff1a; 传送门&#xff1a; https://www.luogu.com.cn/problem/P9303 代码注释 #include <iostream> #include <vecto…...

    NodeMediaEdge接入NodeMediaServer

    如何使用NME接入NMS 简介 NodeMediaEdge是一款部署在监控摄像机网络前端中&#xff0c;拉取Onvif或者rtsp/rtmp/http视频流并使用rtmp/kmp推送到公网流媒体服务器的工具。 通过云平台协议注册到NodeMediaServer后&#xff0c;可以同NodeMediaServer结合使用。使用图形化的管理…...

    【Java基础-环境搭建-创建项目】IntelliJ IDEA创建Java项目的详细步骤

    在Java开发的世界里&#xff0c;选择一个强大的集成开发环境&#xff08;IDE&#xff09;是迈向高效编程的第一步。而IntelliJ IDEA无疑是Java开发者中最受欢迎的选择之一。它以其强大的功能、智能的代码辅助和简洁的用户界面&#xff0c;帮助无数开发者快速构建和部署Java项目…...

    WebSocket指数避让与重连机制

    1. 引言 在现代Web应用中&#xff0c;WebSocket技术已成为实现实时通信的重要手段。与传统的HTTP请求-响应模式不同&#xff0c;WebSocket建立持久连接&#xff0c;使服务器能够主动向客户端推送数据&#xff0c;极大地提升了Web应用的实时性和交互体验。然而&#xff0c;在实…...

    DrissionPage WebPage模式:动态交互与高效爬取的完美平衡术

    在Python自动化领域&#xff0c;开发者常面临两难选择&#xff1a;Selenium虽能处理动态页面但效率低下&#xff0c;Requests库轻量高效却难以应对JavaScript渲染。DrissionPage的WebPage模式创新性地将浏览器控制与数据包收发融为一体&#xff0c;为复杂网页采集场景提供了全新…...

    adb查看、设置cpu相关信息

    查内存 adb shell dumpsys meminfo查CPU top -m 10打开 system_monitor adb shell am start -n eu.chainfire.perfmon/.LaunchActivity设置CPU的核心数 在/sys/devices/system/cpu目录下可以看到你的CPU有几个核心&#xff0c;如果是双核&#xff0c;就是cpu0和cpu1&#xff0c…...

    PHP7+MySQL5.6 查立得源码授权系统DNS验证版

    # PHP7MySQL5.6 查立得源码授权系统DNS验证版 ## 一、系统概述 本系统是一个基于PHP7和MySQL5.6的源码授权系统&#xff0c;使用DNS TXT记录验证域名所有权&#xff0c;实现对软件源码的授权保护。 系统支持多版本管理&#xff0c;可以灵活配置不同版本的价格和下载路径&#…...

    68元开发板,开启智能硬件新篇章——明远智睿SSD2351深度解析

    在智能硬件开发领域&#xff0c;开发板的选择至关重要。它不仅关系到项目的开发效率&#xff0c;还直接影响到最终产品的性能与稳定性。而今天&#xff0c;我要为大家介绍的这款明远智睿SSD2351开发板&#xff0c;仅需68元&#xff0c;却拥有远超同价位产品的性能与功能&#x…...

    【QQ音乐】sign签名| data参数加密 | AES-GCM加密 | webpack (下)

    1.目标 网址&#xff1a;https://y.qq.com/n/ryqq/toplist/26 我们知道了 sign P(n.data)&#xff0c;其中n.data是明文的请求参数 2.webpack生成data加密参数 那么 L(n.data)就是密文的请求参数。返回一个Promise {<pending>}&#xff0c;所以L(n.data) 是一个异步函数…...

    基于netmiko模块实现支持SSH or Telnet的多线程多厂商网络设备自动化巡检脚本

    自动化巡检的需求 巡检工作通常包含大量的重复性操作&#xff0c;而这些重复性特征意味着其背后存在明确的规则和逻辑。这种规律性为实现自动化提供了理想的前提条件。 自动化工具 我们这里采用python作为自动化的执行工具。 过程 安装 netmiko pip install netmiko 模块的使…...

    不用 apt 的解决方案(从源码手动安装 PortAudio)

    第一步&#xff1a;下载并编译 PortAudio 源码 cd /tmp wget http://www.portaudio.com/archives/pa_stable_v190600_20161030.tgz tar -xvzf pa_stable_v190600_20161030.tgz cd portaudio# 使用 cmake 构建&#xff08;推荐&#xff09;&#xff1a; mkdir build &&…...

    【前端】JS引擎 v.s. 正则表达式引擎

    JS引擎 v.s. 正则表达式引擎 它们的转义符都是\ 经过JS引擎会进行一次转义 经过正则表达式会进行一次转义在一次转义中\\\\\的转义过程&#xff1a; 第一个 \ (转义符) 会“吃掉”第二个 \&#xff0c;结果是得到一个字面量的 \。 第三个 \ (转义符) 会“吃掉”第四个 \&#x…...