32RTC&BKP

时间:2024-02-21 19:48:32

目录

一.时间戳

二.BKP简介 

三.RTC外设简介 

​编辑四.相关寄存器 

五.相关函数

 六.代码实现

(1)读写备份寄存器

(2)实时时钟


一.时间戳

最早在Unix系统上使用 

Linux,Windos,安卓的底层计时系统

好处:

1.简化硬件电路,直接采样一个秒寄存器来进行存储

2.在进行一些时间间隔的计算时非常方便

3.存储较方便,一个变量即可

但比较占用软件资源,需要进行秒分时年月日计算

STM32内部定义的变量、是一个无符号的32为整形数据,可以持续到2106年

每次产生闰秒时,时间戳的时间和标准时间会产生一秒的偏差

 

二.BKP简介 

后备寄存器 

VBAT(V Battery)备用电池电源

TAMPER引脚,对应PC-13-TAMPER-RTC,对应PC13引脚,可以用于设计侵入检测功能

校准时钟可以对内部RTC微小误差进行校准,可以配合校准寄存器

闹钟脉冲或者秒脉冲,可以输出为其他设备提供信号

三.RTC外设简介 

在51中,DS1302是外设的 RTC芯片,可以进行独立计时

而在STM32内部,具有RTC外设

高速时钟供内部程序运行和主要外设使用

低速时钟供RTC,看门狗使用,LSE时钟为了省电默认是关闭的

四.相关寄存器 

设计成16位可以简化电路设计

 

五.相关函数

BKP

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);//RTC时钟输出功能配置
void BKP_SetRTCCalibrationValue(uint8_t CalibrationValue);//设置RTC校准值
void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data);//写备份寄存器
uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR);//读备份寄存器
FlagStatus BKP_GetFlagStatus(void);
void BKP_ClearFlag(void);
ITStatus BKP_GetITStatus(void);
void BKP_ClearITPendingBit(void);

PWR

void PWR_BackupAccessCmd(FunctionalState NewState);//备份寄存器使能,设置DBP

rcc.h 

void RCC_LSEConfig(uint8_t RCC_LSE);//配置LSE外部低速时钟
void RCC_LSICmd(FunctionalState NewState);//配置LSI内部低速时钟
void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource);//选择时钟源
void RCC_RTCCLKCmd(FunctionalState NewState);//使能

FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG);//LSE启动标志位

 rtc.h

void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState);
void RTC_EnterConfigMode(void);//进入配置模式,设置CNF位
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);

 六.代码实现

(1)读写备份寄存器

main.c

#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 Num;

int main(void)
{
	OLED_Init();
	Key_Init();
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
	
	PWR_BackupAccessCmd(ENABLE);
	OLED_ShowString(1,1,"W:");
	OLED_ShowString(2,1,"R:");

	while(1)
	{
		Num = Keynum();
		if(Num == 1)
		{
			ArrayWrite[0]++;
			ArrayWrite[1]++;
			
			BKP_WriteBackupRegister(BKP_DR1,ArrayWrite[0]);
			BKP_WriteBackupRegister(BKP_DR2,ArrayWrite[1]);
			
			OLED_ShowHexNum(1,3,ArrayWrite[0],4);
			OLED_ShowHexNum(1,8,ArrayWrite[1],4);
			
			ArrayRead[0] = BKP_ReadBackupRegister(BKP_DR1);
			ArrayRead[1] = BKP_ReadBackupRegister(BKP_DR2);			
		}
		
		OLED_ShowHexNum(2,3,ArrayRead[0],4);
		OLED_ShowHexNum(2,8,ArrayRead[1],4);

		
	}	
}
	

(2)实时时钟

MyRTC.c

#include "stm32f10x.h"                  // Device header
#include <time.h>
uint16_t Mytime[6] = {2024,2,20,23,59,55};

void MyRTC_SET(void);

void MyRTC_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
	
	PWR_BackupAccessCmd(ENABLE);
	
	if(BKP_ReadBackupRegister(BKP_DR1) != 0x12)
	{
		RCC_LSEConfig(RCC_LSE_ON);
		while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) != SET);
		
		RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//需要选择LSE时钟
		RCC_RTCCLKCmd(ENABLE);
	
		RTC_WaitForLastTask();
		RTC_WaitForSynchro();
	
		RTC_SetPrescaler(32768 - 1);
		RTC_WaitForLastTask();
		MyRTC_SET();
		BKP_WriteBackupRegister(BKP_DR1,0x12);
	}
	else
	{
		RTC_WaitForLastTask();
		RTC_WaitForSynchro();
	}
	
}
void MyRTC_SET(void)//输入北京时间,转化为伦敦时间
{
	time_t time_cnt;
	struct tm time_st;
	time_st.tm_year =Mytime[0]-1900;
	time_st.tm_mon =Mytime[1]-1;
	time_st.tm_mday = Mytime[2];
	time_st.tm_hour =Mytime[3];
	time_st.tm_min = Mytime[4];
	time_st.tm_sec =Mytime[5] ;
	time_cnt = mktime(&time_st) - 8*60*60;
	RTC_SetCounter(time_cnt);
	RTC_WaitForLastTask();
}
void MyRTC_READ(void)//读取伦敦时间,转换为北京时间
{
	time_t time_cnt;
	struct tm time_st;
	time_cnt = RTC_GetCounter() + 8*60*60;
	time_st = *localtime(&time_cnt);
	Mytime[0]=time_st.tm_year+1900;
	Mytime[1]=time_st.tm_mon+1;
	Mytime[2]=time_st.tm_mday;
	Mytime[3]=time_st.tm_hour;
	Mytime[4]=time_st.tm_min;
	Mytime[5]=time_st.tm_sec;
	
}

main.c 

#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,"    -  -  ");
	OLED_ShowString(2,1,"  :  :  ");
	OLED_ShowString(3,1,"CNT:");
	OLED_ShowString(4,1,"DIV:");
	while(1)
	{
		MyRTC_READ();
		OLED_ShowNum(1,1,Mytime[0],4);
		OLED_ShowNum(1,6,Mytime[1],2);
		OLED_ShowNum(1,10,Mytime[2],2);
		OLED_ShowNum(2,1,Mytime[3],2);
		OLED_ShowNum(2,4,Mytime[4],2);
		OLED_ShowNum(2,7,Mytime[5],2);
		OLED_ShowNum(3,5,RTC_GetCounter(),10);
		OLED_ShowNum(4,5,(32767-RTC_GetDivider())/32767.0*999,10);//需要加上小数点
		//可以读取DIV,对其进行线性变换,读取任意时刻的毫秒

		
	}	
}
	

相关文章