12-3读写备份寄存器&实时时钟

常用函数

1
void BKP_DeInit(void);

BKP_DeInit恢复缺省配置,手动清空BKP所有的数据寄存器。

1
void BKP_TamperPinLevelConfig(uint16_t BKP_TamperPinLevel);

用于配置TAMPER侵入检测功能,配置TAMPER引脚有效电平,高电平触发还是低电平触发。

1
void BKP_TamperPinCmd(FunctionalState NewState);

用于配置TAMPER侵入检测功能,是否开启侵入检测功能。

1
void BKP_ITConfig(FunctionalState NewState);

中断配置,是否开启中断。

1
void BKP_RTCOutputConfig(uint16_t BKP_RTCOutputSource);

时钟输出功能,可以选择在RTC引脚上输出时钟信号,输出RTC校准时钟,RTC闹钟脉冲或秒脉冲。

1
void BKP_SetRTCCalibrationValue(uint8_t CalibrationValue);

设置RTC校准值,写入RTC校准寄存器。

1
void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data);

写备份寄存器,第一个参数指定,写在哪个DR里,第二个参数指定要写入的数据。

1
uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR);

读备份寄存器,参数指定要读哪个DR。

1
FlagStatus BKP_GetFlagStatus(void);

获取BKP状态

1
void BKP_ClearFlag(void);

清除BKP侵入检测寄存器状态。

1
ITStatus BKP_GetITStatus(void);

获取侵入检测的中断状态。

1
void BKP_ClearITPendingBit(void);

清除侵入检测的中断挂起位。

1
void PWR_BackupAccessCmd(FunctionalState NewState);

备份寄存器访问使能。设置PWR_CR的DBP,使能对BKP和RTC的访问。

1
void RCC_LSEConfig(uint8_t RCC_LSE);

配置LSE外部低速时钟

1
void RCC_LSICmd(FunctionalState NewState);

配置LSI内部低速时钟

1
void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource);

RTCCLK配置,选择RTCCLK时钟源

1
void RCC_RTCCLKCmd(FunctionalState NewState);

RTCCLK使能,调用上面函数选择时钟之后,使能。

1
FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG);

获取RCC标志位,调用启动时钟函数之后,要等待标志位,LSERDY置1后,才算启动完成。

1
void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState);

配置RTC中断输出

1
void RTC_EnterConfigMode(void);

进入配置模式,CNF位置1。

1
void RTC_ExitConfigMode(void);

RTC退出配置模式,把CNF位置0。

1
uint32_t  RTC_GetCounter(void);

RTC获取CNT计数器的值。用于读取时钟。

1
void RTC_SetCounter(uint32_t CounterValue);

写入CNT计数器的值。用于设置时间。

1
void RTC_SetPrescaler(uint32_t PrescalerValue);

写入预分频器,写入到预分频的PRL重装寄存器中,配置预分频器的分频系数。

1
void RTC_SetAlarm(uint32_t AlarmValue);

写入闹钟值,用于配置闹钟。

1
uint32_t  RTC_GetDivider(void);

获取预分频器中的DIV余数寄存器。余数寄存器是一个自减计数器,获取这个值,一般是为了获取更细致的时间。

1
void RTC_WaitForLastTask(void);

等待上次操作完成。

1
void RTC_WaitForSynchro(void);

等待同步。清除RSF标志位,然后循环,直到RSF为1。

1234
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);

RTC标志位相关函数。

读写备份寄存器

main.c

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
#include "stm32f10x.h"                  // Device header#include "Delay.h"#include "OLED.h"#include "key.h" uint16_t ArrayWrite[] = {0x1234,0x5678};//存放写入数据的数组uint16_t ArrayRead[2];//存放读取数据的数组uint8_t KeyNum; int main(void){	OLED_Init();	KEY_Init(); 	OLED_ShowString(1,1,"W:");	OLED_ShowString(2,1,"R:"); 	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//开启APB1的PWR外设时钟	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);//开启APB1的BKP外设时钟 	PWR_BackupAccessCmd(ENABLE);//使能PWR  	//BKP_WriteBackupRegister(BKP_DR1,0x1234);//BKP写入,在BKPDR1中写入了0x1234	//OLED_ShowHexNum(1,1,BKP_ReadBackupRegister(BKP_DR1),4);//OLED显示写入的值 	while(1)	{		KeyNum = Key_GetNum();//获取按钮状态 		if(KeyNum == 1)		{			ArrayWrite[0]++;//写入的数据自增1			ArrayWrite[1]++; 			BKP_WriteBackupRegister(BKP_DR1,ArrayWrite[0]);//把ArrayWrite[0]的数据写入到DR1中			BKP_WriteBackupRegister(BKP_DR2,ArrayWrite[1]);//把ArrayWrite[1]的数据写入到DR2中 			OLED_ShowHexNum(1,3,ArrayWrite[0],4);			OLED_ShowHexNum(1,8,ArrayWrite[1],4);		}		ArrayRead[0] = BKP_ReadBackupRegister(BKP_DR1);//读取BKPDR1的值,放到ArrayRead[0]中		ArrayRead[1] = BKP_ReadBackupRegister(BKP_DR2);//读取BKPDR2的值,放到ArrayRead[1]中 		OLED_ShowHexNum(2,3,ArrayRead[0],4);		OLED_ShowHexNum(2,8,ArrayRead[1],4);	}}

实时时钟

main.c

123456789101112131415161718192021222324252627
#include "stm32f10x.h"                  // Device header#include "Delay.h"#include "OLED.h"#include "MyRTC.h" int main(void){	OLED_Init();	MyRTC_Init(); 	OLED_ShowString(1,1,"Date:XXXX-XX-XX");	OLED_ShowString(2,1,"Time:XX:XX:XX");	OLED_ShowString(3,1,"CNT:");	OLED_ShowString(4,1,"DIV:");	while(1)	{		MyRTC_ReadTime();		OLED_ShowNum(1,6,MyRTC_Time[0],4);		OLED_ShowNum(1,11,MyRTC_Time[1],2);		OLED_ShowNum(1,14,MyRTC_Time[2],2);		OLED_ShowNum(2,6,MyRTC_Time[3],2);		OLED_ShowNum(2,9,MyRTC_Time[4],2);		OLED_ShowNum(2,12,MyRTC_Time[5],2);		OLED_ShowNum(3,6,RTC_GetCounter(),10);		OLED_ShowNum(4,6,RTC_GetDivider(),10);	}}

MyRTC.c

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
#include "stm32f10x.h"                  // Device header#include <time.h> uint16_t MyRTC_Time[] = {2023,1,1,23,59,55}; 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;//得到秒数,偏移8小时 	RTC_SetCounter(time_cnt);//秒数写入到RTC的CNT中	RTC_WaitForLastTask();//等待写入时间完成} void MyRTC_Init(void){	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//开启PWR时钟	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);//开启BKP时钟	PWR_BackupAccessCmd(ENABLE); 	if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)//判断DR1中的值是否为0xA5A5,用于判断是否完全断电	{		//开启LSE时钟,并等待LSE时钟启动完成		RCC_LSEConfig(RCC_LSE_ON);//LSE振荡器打开		while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) != SET);//获取标志位,LSE时钟启动完成 		//选择RTCCLK时钟源		RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//RTCCLK时钟源选择LSE时钟		RCC_RTCCLKCmd(ENABLE);//使能RTCCLK时钟 		//等待同步和等待上一次写入操作完成		RTC_WaitForSynchro();//等待同步		RTC_WaitForLastTask();//等待上一次操作完成 		//配置预分频器		RTC_SetPrescaler(32768-1);		RTC_WaitForLastTask();//等待写入预分频值完成 		//RTC_SetCounter(1672588795);//设置初始时间		//RTC_WaitForLastTask();//等待写入时间完成 		MyRTC_SetTime(); 		BKP_WriteBackupRegister(BKP_DR1,0xA5A5);	}	else	{		//等待同步和等待上一次写入操作完成		RTC_WaitForSynchro();//等待同步		RTC_WaitForLastTask();//等待上一次操作完成	}}   void MyRTC_ReadTime(void){	time_t time_cnt;	struct tm time_date;	//得到秒数	time_cnt = RTC_GetCounter() + 8*60*60;//偏移8小时	time_date = *localtime(&time_cnt); 	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; }  
🔍 ×