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

article/2025/7/15 10:43:15

什么是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);}
    }

    http://www.hkcw.cn/article/hPNFueVwXu.shtml

    相关文章

    antDesignVue中a-upload上传组件的使用

    工作中需要使用上传组件,记录一下a-upload部分属性用法 1.showUploadList属性使用 使用:showUploadList"{ showRemoveIcon: true ,showDownloadIcon: true }"属性可控制右侧下载,删除图标 2.如何实现回显功能 使用:defaultFileList"fil…

    基于RK3568/RK3588/全志H3/飞腾芯片/音视频通话程序/语音对讲/视频对讲/实时性好/极低延迟

    一、前言说明 近期收到几个需求都是做音视频通话,很多人会选择用webrtc的方案,这个当然是个不错的方案,但是依赖的东西太多,而且相关组件代码量很大,开发难度大。所以最终选择自己属性的方案,那就是推流拉…

    借助DS用python帮你编写脚本(辅助开发测试)

    最近在做一个音频采集识别项目,采集20HZ到20KHZ各个频带最大分贝数(DB),需要用到各个频段的测试音频来验证程序的正确性。 借助Deepseek,原本对python编程没有学过,也能轻松学会。 提问:pytho…

    【图像处理基石】如何进行图像畸变校正?

    图像畸变校正常用于计算机视觉、摄影测量学和机器人导航等领域,能够修正因镜头光学特性或传感器排列问题导致的图像失真。下面我将介绍几种常用的图像畸变校正算法,并提供Python实现和测试用例。 常用算法及Python实现 1. 径向畸变校正 径向畸变是最常…

    技术创新如何赋能音视频直播行业?

    在全球音视频直播行业的快速发展中,技术的持续创新始终是推动行业进步的核心动力。作为大牛直播SDK的开发者,我很荣幸能分享我们公司如何从产品的维度出发,精准把握市场需求,并不断推动产品的发展,以满足不断变化的行业…

    我的世界服务端搭建

    文章目录 我的世界服务端搭建使用forge搭建服务端确保服务器的 Java 环境安装1.20.1服务端配置文件修改启动游戏服务器 Minecraft server.properties 文件解析**基础设置****世界设置****网络与安全****性能优化****高级功能****配置文件示例****注意事项**Minecraft 白名单系统…

    官宣正式分手 特朗普马斯克说了什么临别感言

    官宣正式“分手” 特朗普马斯克都说了什么“临别感言”当地时间5月30日,美国总统特朗普和美国企业家、政府效率部负责人埃隆马斯克在白宫举行新闻发布会。特朗普称赞“政府效率部”成就在发布会上,特朗普对马斯克领导的“政府效率部”所达成的成就表示称赞,他称“政府效率部…

    STM32通过rt_hw_hard_fault_exception中的LR寄存器追溯程序问题​

    1. 问题现象 程序运行导致rt_hw_hard_fault_exception 如图 显示错误相关代码 struct exception_stack_frame {uint32_t r0;uint32_t r1;uint32_t r2;uint32_t r3;uint32_t r12; uint32_t lr; // 链接寄存器 (LR)uint32_t pc; // 程序计数器 (PC)uint32_t psr; // 程序状态…

    AgenticSeek,开源本地通用AI Agent,自主执行任务

    AgenticSeek是一款完全本地化的开源AI助手,作为Manus的开源替代品,专为保护用户隐私而设计。它能够在本地设备上执行多种任务,包括网页浏览、代码编写和复杂项目的规划,确保所有操作和数据均在用户的设备上完成。 AgenticSeek是什…

    深入理解 Java 反射机制:动态编程的核心利器

    一、反射机制的本质与核心价值 在 Java 的世界里,反射机制(Reflection)被视为连接静态编译与动态执行的桥梁。当程序运行时,反射允许我们在内存中动态获取类的完整结构信息,并对类的成员(字段、方法、构造…

    群晖synology nas安装curl教程

    在群晖nas系统上发现没有curl这个命令,想通过opkg进行安装,发现opkg这个套件也没有,本章教程介绍如何安装opkg,并通过opkg 安装上curl命令工具,nas的系统版本是:x86_64 GNU/Linux synology_apollolake_918+ 一、安装opkg wget -O - http://bin.entware.net/x64-k3.2/inst…

    非接触式数据引擎:RFID重塑锂电注液工艺实时交互生态

    非接触式数据引擎:RFID重塑锂电注液工艺实时交互生态 浙江某锂电行业注液机上存在问题: 1.在锂电池制造的核心环节中,注液工艺直接影响电芯的电化学性能与安全稳定性。随着行业对电池一致性、生产效率及追溯能力的需求升级。 2.按设定的抽…

    Shell基础命令

    一、设置修改主机名称 1.文件方式(重启生效) 2.命令方式(立即生效) hostnamectl set-hostname myname 二、网络管理nmcli (NetworkManager command-line interface) nmcli 1、查看网卡 2、设置网卡 dhcp网络工作模式 静态网…

    【JVM】Java程序运行时数据区

    运行时数据区 运行时数据区是Java程序执行过程中管理的内存区域 Java 运行时数据区组成(JVM 内存结构) Java 虚拟机(JVM)的运行时数据区由以下核心部分组成: 线程私有:程序计数器、Java虚拟机栈、本地方…

    力扣面试150题--二叉树的层平均值

    Day 54 题目描述 思路 初次做法(笨):使用两个队列,一个队列存放树的节点,一个队列存放对应节点的高度,使用x存放上一个节点,highb存放上一个节点的高度,sum存放当前层的节点值之和…

    机器学习与深度学习01--线性回归

    目录 1.什么是线性回归2.如何用数学方式描述简单线性回归模型3.什么是最小二乘法,他有什么作用 1.什么是线性回归 线性回归是⼀种⼴泛⽤于统计学和机器学习中的回归分析⽅法,⽤于建⽴⾃变量(特征)与因变量(⽬标&#…

    004时装购物系统技术解析:构建智能时尚消费平台

    时装购物系统技术解析:构建智能时尚消费平台 在电商行业蓬勃发展的当下,时装购物系统凭借其便捷性与多样性,成为消费者选购时尚单品的重要渠道。该系统通过商品信息、订单管理等核心模块,结合前台展示与后台录入功能,…

    无线通信模块简介

    QuecPython 是运行在无线通信模块上的开发框架。对于首次接触物联网开发的用户而言,无线通信模块可能是一个相对陌生的概念。本文主要针对无线通信和蜂窝网络本身,以及模块的概念、特性和开发方式进行简要的介绍。 无线通信和蜂窝网络 物联网对无线通信…

    从认识AI开始-----解密门控循环单元(GRU):对LSTM的再优化

    前言 在此之前,我已经详细介绍了RNN和LSTM,RNN虽然在处理序列数据中发挥了重要的作用,但它在实际使用中存在长期依赖问题,处理不了长序列,因为RNN对信息的保存只依赖一个隐藏状态,当序列过长,隐…

    历年西北工业大学计算机保研上机真题

    2025西北工业大学计算机保研上机真题 2024西北工业大学计算机保研上机真题 2023西北工业大学计算机保研上机真题 在线测评链接:https://pgcode.cn/school 计算整数乘积 题目描述 给定 n n n 组数,每组两个整数,输出这两个整数的乘积。 …