RTC实时时钟

一、Unix时间戳

1、Unix 时间戳

(1)Unix 时间戳(Unix Timestamp)定义为从UTC/GMT 的1970年1月1日0时0分0秒开始所经过的秒数,不考虑闰秒

(2)时间戳 存储在一个秒计数器 中,秒计数器为32位/64位整型变量

(3)世界上所有时区的秒计数器相同不同时区 通过添加偏移来得到当地时间

2、UTC/GMT

(1)GMT(Greenwich Mean Time)格林尼治标准时间 是一种以地球自转为基础的时间计量系统 。它将地球自转一周的时间间隔等分为24小时,以此确定计时标准

(2)UTC(Universal Time Coordinated)协调世界时 是一种以原子钟为基础的时间计量系统 。它规定铯133原子基态的两个超精细能级间在零磁场下跃迁辐射9,192,631,770周所持续的时间为1秒 。当原子钟计时一天的时间地球自转一周的时间相差超过0.9秒时UTC会执行闰秒 来保证其计时与地球自转的协调一致

3、时间戳转换

C语言的time.h模块 提供了时间获取时间戳转换 的相关函数,可以方便地进行秒计数器日期时间字符串之间的转换

二、BKP简介

1、BKP(Backup Registers)备份寄存器

(1)BKP可用于存储用户应用程序数据 。当VDD(系统的主电源)(2.0~3.6V)电源被切断,他们仍然由VBAT(备用电池电源)(1.8~3.6V)维持供电 。当系统在待机模式下被唤醒,或系统复位或电源复位时,他们也不会被复位

(2)TAMPER引脚产生的侵入事件将所有备份寄存器内容清除

(3)RTC引脚 输出RTC校准时钟RTC闹钟脉冲或者秒脉冲

(4)存储RTC时钟校准寄存器

(5)用户数据存储容量

20字节 (中容量和小容量)/84字节(大容量和互联型)

2、BKP基本结构

三、RTC简介

1、RTC(Real Time Clock)实时时钟

(1)RTC是一个独立的定时器 ,可为系统提供时钟日历的功能

(2)RTC时钟配置 系统处于后备区域系统复位时数据不清零VDD(2.0~3.6V)断电 后可借助VBAT(1.8~3.6V)供电继续走时

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

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

(5)可选择三种RTC时钟源

HSE时钟 除以128 (通常为8MHz/128

LSE振荡器时钟 (通常为32.768KHz)2^15=32768

LSI振荡器时钟40KHz

2、RTC框图

3、RTC基本结构

4、硬件电路

5、RTC操作注意事项

(1)执行以下操作将使能对BKP和RTC的访问

设置RCC_APB1ENRPWRENBKPEN使能PWR和BKP时钟

设置PWR_CRDBP使能对BKP和RTC的访问

(2)若在读取RTC寄存器 时,RTC的APB1接口 曾经处于禁止状态 ,则软件 首先必须等待RTC_CRL寄存器中的RSF位(寄存器同步标志)被硬件置1

(3)必须设置RTC_CRL寄存器中的CNF 位,使RTC进入配置模式 后,才能写入RTC_PRL、RTC_CNT、RTC_ALR寄存器

(4)对RTC任何寄存器的写操作 ,都必须在前一次写操作结束后进行 。可以通过查询RTC_CR寄存器中的RTOFF状态位判断RTC寄存器是否处于更新中 。仅当RTOFF状态位是1时,才可以写入RTC寄存器

四、读写备份寄存器

1、按照以下接线方式连接,并将STLINK插到电脑上

2、BKP函数驱动模块

(1)BKP库函数的功能

(2)PWR库函数的功能

3、 mian.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "button.h"

uint8_t KeyNum;

uint16_t ArrayWrite[] ={0x1234,0x5678};
uint16_t ArrayRead[2];

int main(void)
{
	OLED_Init();
	Button_Init();
	
	OLED_ShowString(1,1,"W:");
	OLED_ShowString(2,1,"R:");
	
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);	//BKP初始化,使能PWR和BKP时钟 
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);
	
	PWR_BackupAccessCmd(ENABLE);//对BKP的访问
		
	while(1)
	{
		KeyNum = Button_GetNum();
		if(KeyNum == 1)
		{
			ArrayWrite[0]++;
			ArrayWrite[1]++;
			
			BKP_WriteBackupRegister(BKP_DR1,ArrayWrite[0]);	//写BKP寄存器
			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);		//读BKP寄存器
		ArrayRead[1] = BKP_ReadBackupRegister(BKP_DR2);
		
		OLED_ShowHexNum(2,3,ArrayRead[0],4);
		OLED_ShowHexNum(2,8,ArrayRead[1],4);
	}   
}

4、实现效果

读写备份寄存器

掉电不丢失

五、实时时钟

1、按照以下接线方式连接,并将STLINK插到电脑上

2、RTC函数驱动模块

(1)RCC库函数的功能

(2)RTC库函数的功能

(3)MyRTC.c

#include "stm32f10x.h"                  // Device header
#include <time.h>

uint16_t MyRTC_Time[] = {2023,1,1,23,59,55};

void MyRTC_SetTime(void);

void MyRTC_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);	//开启PWR和BKP时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);
	
	PWR_BackupAccessCmd(ENABLE);						//使能BKP和RTC访问
	
	if(BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)//避免时间重置,只有在备用电源也掉电的时候时间才重置
	{
		RCC_LSEConfig(RCC_LSE_ON);//启动外部LSE晶振
		while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) != SET);//等待LSE启动完成
		
		RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//选择RTCCLK时钟源:LSE时钟
		RCC_RTCCLKCmd(ENABLE);//使能一下时钟
		
		RTC_WaitForSynchro();//等待同步
		RTC_WaitForLastTask();//等待上一次操作完成
		
		RTC_SetPrescaler(32768 - 1);//设置预分频器,1Hz
		RTC_WaitForLastTask();//等待上一次操作完成
		
		MyRTC_SetTime();
		
		BKP_WriteBackupRegister(BKP_DR1,0xA5A5);
	}	
	else
	{
		RTC_WaitForSynchro();//等待同步
		RTC_WaitForLastTask();//等待上一次操作完成
	}
}

/*
	设置时间
*/
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;
	
	RTC_SetCounter(time_cnt);
	RTC_WaitForLastTask();//等待上一次操作完成
}

/*
	读取时间
*/
void MyRTC_ReadTime(void)
{
	time_t time_cnt;
	struct tm time_date;
	
	time_cnt = RTC_GetCounter() +8*60*60;//获取计数器的值
	
	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;
}

(4)MyRTC.h

#ifndef __MYRTC_H
#define __MYRTC_H

extern uint16_t MyRTC_Time[];

void MyRTC_Init(void);
void MyRTC_SetTime(void);
void MyRTC_ReadTime(void);

#endif

3、编写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,"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);//余数寄存器,自减32767~0
	}
}

4、实现效果

实时时钟

掉电不丢失

相关推荐
番茄灭世神8 小时前
利用STM32的定时器输出PWM方波
stm32·单片机·嵌入式硬件
南耿先生12 小时前
我在高职教STM32——LCD液晶显示(1)
stm32·单片机·嵌入式硬件
莫邪博客13 小时前
【STM32修改串口波特率】
stm32·单片机·嵌入式硬件
南耿先生16 小时前
我在高职教STM32——时钟系统与延时控制(1)
stm32·单片机·嵌入式硬件
致亲爱的开心eng小电21 小时前
【stm32】大一上学期笔记复制
笔记·stm32·嵌入式硬件
main工作室1 天前
详细讲解 Keil Pack Installer,以及通过 Keil 官网获取 Pack
stm32·32 单片机·keil uvision5 系列教程
极客小张2 天前
基于STM32的PWM实现LED调光效果详解
c++·stm32·单片机·嵌入式硬件·物联网·iot
嵌入式详谈2 天前
基于STM32的智能电池管理系统
stm32·单片机·嵌入式硬件
正点原子2 天前
《DNK210使用指南 -CanMV版 V1.0》第六章 Kendryte K210固件烧录
c语言·stm32·ai·嵌入式开发·canmv·正点原子·嘉楠k210
IoT_H22 天前
GD32 开发笔记
stm32·单片机·嵌入式硬件·gd32