24:RTC实时时钟

RTC实时时钟

1、时间戳

c 复制代码
#include <stdio.h>
#include <time.h>

time_t ourtime;				// time_t = int64_t;
struct tm day;
struct tm day1;
struct tm day2;

int main(void)
{
	//t = time(NULL);//获取伦敦的时间戳的秒数,
	time(&ourtime);
	printf("伦敦的时间戳:%d\n",ourtime);
	
	long long int d = ourtime + 28800;
	printf("本地的时间戳:%d\n",d);
		
	day = *gmtime(&ourtime);//转换为伦敦的年月日时分秒
	printf("伦敦时间:%d-%d-%d %d:%d:%d。\n",day.tm_year+1900,day.tm_mon+1,day.tm_mday
						,day.tm_hour,day.tm_min,day.tm_sec);
	
	day1 = *gmtime(&d);//转换为本地的年月日时分秒
	printf("本地时间:%d-%d-%d %d:%d:%d。\n",day1.tm_year+1900,day1.tm_mon+1,day1.tm_mday
						,day1.tm_hour,day1.tm_min,day1.tm_sec);
	
	day2 = *localtime(&ourtime);//转换为当地的年月日时分秒
	printf("本地时间:%d-%d-%d %d:%d:%d。\n",day2.tm_year+1900,day2.tm_mon+1,day2.tm_mday
						,day2.tm_hour,day2.tm_min,day2.tm_sec);
	
	ourtime = mktime(&day2);//将本地的日期转换为伦敦的时间戳
	printf("伦敦的时间戳:%d\n",ourtime);
	
	char t[50];
	strftime(t,50,"%Y-%m-%d %H:%M:%S",&day1);//打印自定义的时间格式
	printf("本地时间:%s\n",t);
	
	return 0;
}

伦敦的时间戳:1725763707

本地的时间戳:1725792507

伦敦时间:2024-9-8 2:48:27。

本地时间:2024-9-8 10:48:27。

本地时间:2024-9-8 10:48:27。

伦敦的时间戳:1725763707

本地时间:2024-09-08 10:48:27

2、BKP备份寄存器

2.1:简介

1、备份寄存器,用于存储数据,当VDD电源被切断时,这个备份寄存器由VBAT维持供电。如果VBAT电源也被切断,那么里面的数据就会被清除。当系统在待机模式下被唤醒,或系统复位或电源复位时,也不会被复位。

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

3、用户数据存储容量:

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

2.2:基本结构

由上图所示:一个数据寄存器DR只能存储2个字节,而中容量和小容量只能存储20个字节,所以BKP中的数据寄存器DR只有10个。除了由数据寄存器,还有RTC的控制寄存器和状态寄存器和RTC时钟校准寄存器。

3、RTC时钟

RTC是一个独立的定时器,本质就是一个计时器。RTC和时钟配置系统处于后备区域,VDD(2.0~3.6V)断电后可借助VBAT (1.8~3.6V)供电继续走时。但是如果系统复位或电源复位时,秒计数器里面会从初始值开始计数

1、32位的可编程计数器,可对应Unix时间戳的秒计数器

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

3、可选择三种RTC时钟源:

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

LSE振荡器时钟(通常为32.768KHz)

LSI振荡器时钟(40KHz)

时钟来源:

如上图所示:RTC的时钟来源一般是LSE32.768KHz,而20位RTC预分频器设置为2^15,则正好为1Hz。而且只有这一路的时钟由备用电池VBAT供电。

注意事项:

4、读写备份寄存器BKP

标准库的编程接口:

c 复制代码
/*
	BKP(备份寄存器)数据的写入与读取测试
*/

#include "stm32f10x.h"                 
#include "OLED.h"

uint16_t Data;

int main(void)
{
	OLED_Init();

	//1、开启时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//使能PWR
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);//使能BKP
	
	//2、使能对BKP的访问
	PWR_BackupAccessCmd(ENABLE);//使能对BKP和RTC的访问
	
	//3、写入数据
	BKP_WriteBackupRegister(BKP_DR1,0x1234);//写入数据寄存器DR1
	
	//4、读取数据
	Data = BKP_ReadBackupRegister(BKP_DR1);//读取数据寄存器DR1的数据
	
	OLED_ShowHexNum(1,1,Data,4);
	while(1)
	{
		
	}
}

5、RTC实时时钟

标准库的编程接口:

RTC.c文件的代码如下:

c 复制代码
#include "stm32f10x.h"                  // Device header
#include <time.h>

uint16_t MyRTC_Time[] = {2024,9,10,21,10,55};//设置时间:年月日时分秒

void MyRTC_SetTime(void);//设置时间的函数
	
void MyRTC_Init(void)
{
	//1、开启PWR和BKP的时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);
	
	//2、使能BKP和RTC的访问
	PWR_BackupAccessCmd(ENABLE);
	
	if(BKP_ReadBackupRegister(BKP_DR1) != 0x1111)//按下复位按钮,BKP中DR1不清除,则不用重装计数器里面的时间戳
	{
		///3、配置时钟源
		RCC_LSEConfig(RCC_LSE_ON);//打开LSE
	
		//4、等待LSE启动完成
		while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
	
		//5、选择RTC时钟源
		RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//选择LSE为时钟源
		RCC_RTCCLKCmd(ENABLE);
	
		//6、等待同步和操作完成
		RTC_WaitForSynchro();//等待同步
		RTC_WaitForLastTask();//等待操作完成
	
		//7、配置预分频器
		RTC_SetPrescaler(32768 - 1);//设置分频系数为32768
		RTC_WaitForLastTask();//等待操作完成
		MyRTC_SetTime();
		BKP_WriteBackupRegister(BKP_DR1,0x1111);
	}
	else
	{
		RTC_WaitForSynchro();//等待同步
	  RTC_WaitForLastTask();//等待操作完成
	}
}

void MyRTC_SetTime(void)//设置时间的函数
{
	time_t ourtime;
	struct tm day;
	
	day.tm_year = MyRTC_Time[0]-1900;
	day.tm_mon = MyRTC_Time[1]-1;
	day.tm_mday = MyRTC_Time[2];
	day.tm_hour = MyRTC_Time[3];
	day.tm_min = MyRTC_Time[4];
	day.tm_sec = MyRTC_Time[5];
	
	ourtime = mktime(&day);//将日期转换为时间戳秒
	
	RTC_SetCounter(ourtime);
	RTC_WaitForLastTask();//等待操作完成
}

void MyRTC_ReadTime(void)
{
	time_t ourtime;
	struct tm day;
	
	ourtime = RTC_GetCounter();//获取RTC计数器的值
	day = *localtime(&ourtime);//将时间戳转换为本地的年月日时分秒
	
	MyRTC_Time[0] = day.tm_year + 1900;//将转换的数据保存在数组中
	MyRTC_Time[1] = day.tm_mon + 1;
	MyRTC_Time[2] = day.tm_mday;
	MyRTC_Time[3] = day.tm_hour;
	MyRTC_Time[4] = day.tm_min;
	MyRTC_Time[5] = day.tm_sec;
}

主程序的代码如下:

c 复制代码
/*
	RTC实时时钟的使用
*/

#include "stm32f10x.h"                 
#include "OLED.h"
#include "MyRTC.h"


int main(void)
{
	OLED_Init();
	MyRTC_Init();

	OLED_ShowString(1,1,"Data:xxxx-xx-xx");
	OLED_ShowString(2,1,"Time:xx:xx:xx");
	OLED_ShowString(3,1,"CNT:");
	
	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,5,RTC_GetCounter(),10);
	}
}
相关推荐
yutian060623 分钟前
Keil MDK下载程序后MCU自动重启设置
单片机·嵌入式硬件·keil
XH华2 小时前
初识C语言之二维数组(下)
c语言·算法
析木不会编程3 小时前
【小白51单片机专用教程】protues仿真独立按键控制LED
单片机·嵌入式硬件·51单片机
Uu_05kkq6 小时前
【C语言1】C语言常见概念(总结复习篇)——库函数、ASCII码、转义字符
c语言·数据结构·算法
枯无穷肉7 小时前
stm32制作CAN适配器4--WinUsb的使用
stm32·单片机·嵌入式硬件
不过四级不改名6777 小时前
基于HAL库的stm32的can收发实验
stm32·单片机·嵌入式硬件
嵌入式科普8 小时前
十一、从0开始卷出一个新项目之瑞萨RA6M5串口DTC接收不定长
c语言·stm32·cubeide·e2studio·ra6m5·dma接收不定长
嵌入式大圣8 小时前
单片机UDP数据透传
单片机·嵌入式硬件·udp
A懿轩A8 小时前
C/C++ 数据结构与算法【栈和队列】 栈+队列详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·栈和队列
云山工作室8 小时前
基于单片机的视力保护及身姿矫正器设计(论文+源码)
stm32·单片机·嵌入式硬件·毕业设计·毕设