【STM32-学习笔记-11-】RTC实时时钟

news2025/1/20 15:21:57

文章目录

  • RTC实时时钟
    • 一、RTC简介
    • 二、RTC框图
    • 三、RTC基本结构
    • 四、RTC操作注意事项
    • 五、RTC函数
    • 六、配置RTC
        • MyRTC.c
    • 七、示例:实时时钟
      • ①、main.c
      • ②、MyRTC.c
      • ③、MyRTC.h

RTC实时时钟

一、RTC简介

  • RTC(Real Time Clock)实时时钟

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

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

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

  • 20位的可编程预分频器,可适配不同频率的输入时钟(产生稳定的1Hz的时钟

  • 可选择三种RTC时钟源:

    • 高速外部时钟信号)HSE时钟除以128(通常为8MHz/128)
      • 主要作为系统时钟
    • 低速外部时钟信号)LSE振荡器时钟(通常为32.768KHz)
      • 主要用于RTC时钟,可由VBAT供电
      • 2 15 = 32768 2^{15}=32768 215=32768 则使用15位的计数器,计数值从0~32767,自然溢出即可产生1Hz的时钟信号
    • 低速内部时钟信号)LSI振荡器时钟(40KHz)
      • 主要作为看门狗时钟
    • image-20250115103618025

二、RTC框图

  • RTC寄存器由RTCCLK寄存器驱动

image-20250115104623366

  • 灰色区域在主电源掉电之后可由VBAT供电
  • RTC_PRL 预分频装载寄存器,用来保存RTC预分频器的周期计数值(写入R则是R+1分频
  • RTC_DIV 预分频器余数寄存器
    • 每来一个脉冲,计数值-1;自减到0时,再来一个脉冲,则会产生一个溢出信号(TR_CLK);同时DIV从PRL获取一个重装值,再继续自减
    • 该溢出信号即为所需的1Hz时钟
  • RTC_CNT (秒计数器)相当于Unix时间戳,再利用<time.h>库函数即可计算出时间
  • RTC_ALR 设置闹钟
    • RTC_ALR=RTC_CNT时,则会产生RTC_Alarm闹钟信号通往NVIC中断控制器

三、RTC基本结构

image-20250115110845391

image-20250115111150460

四、RTC操作注意事项

  1. 使能对BKP(备份寄存器)和RTC的访问

    • 需要设置RCC_APB1ENR寄存器的PWRENBKPEN位,以**

      •   RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
        
    • 需要设置PWR_CR寄存器的DBP位,以使能对BKPRTC的访问

      •   PWR_BackupAccessCmd(ENABLE);
        
  2. 等待寄存器同步标志位被置位

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

      •   while (!(RTC->CRL & RTC_CRL_RSF));  // 等待寄存器同步标志位被置位
        
    • 这是因为在APB1接口禁止状态下,寄存器的值可能不一致,需要等待同步标志位被置位以确保寄存器值的一致性

  3. 进入配置模式

    • 必须设置RTC_CRL寄存器中的CNF位,使RTC进入配置模式后,才能写入RTC_PRL(预分频器)、RTC_CNT(计数器)、RTC_ALR(闹钟寄存器)等寄存器

      •   RTC->CRL |= RTC_CRL_CNF;  // 设置配置模式位
          while (!(RTC->CRL & RTC_CRL_CNF));  // 等待配置模式位被硬件清除
        
  4. 写操作的时序要求:等待前一次写操作结束

    • 对RTC任何寄存器的写操作,都必须在前一次写操作结束后进行

    • 可以通过查询RTC_CR寄存器中的RTOFF状态位,判断RTC寄存器是否处于更新中

    • 仅当RTOFF状态位是1时,才可以写入RTC寄存器。这是因为RTC寄存器在更新过程中是不允许写入的,必须等待更新完成(即RTOFF位被置位)后才能进行下一次写操作

      •   while (!(RTC->CR & RTC_CR_RTOFF));  // 等待上一次写操作完成
          RTC->CNT = new_value;  // 写入新的值
        

五、RTC函数

// 配置RTC中断
void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState);

// 进入RTC配置模式
void RTC_EnterConfigMode(void);
// 退出RTC配置模式
void RTC_ExitConfigMode(void);

// 获取RTC计数器CNT的值
uint32_t  RTC_GetCounter(void);
// 设置RTC计数器CNT的值
void RTC_SetCounter(uint32_t CounterValue);

// 设置RTC预分频值(写入PRL重装寄存器中)
void RTC_SetPrescaler(uint32_t PrescalerValue);

// 设置RTC闹钟值ALR
void RTC_SetAlarm(uint32_t AlarmValue);

// 获取RTC分频值(获取余数寄存器RTC_DIV的值)
uint32_t RTC_GetDivider(void);

// 等待RTC上一个任务完成
void RTC_WaitForLastTask(void);

// 等待RTC同步(等待RSF【寄存器同步标志】置1)
void RTC_WaitForSynchro(void);

// 获取RTC标志位状态
FlagStatus RTC_GetFlagStatus(uint16_t RTC_FLAG);
// 清除RTC标志位
void RTC_ClearFlag(uint16_t RTC_FLAG);

// 获取RTC中断状态
ITStatus RTC_GetITStatus(uint16_t RTC_IT);
// 清除RTC中断待处理位
void RTC_ClearITPendingBit(uint16_t RTC_IT);

六、配置RTC

  1. 开启电源(PWR)和备份寄存器(BKP)时钟

    •   	//开启电源(PWR)和备份寄存器(BKP)时钟
        	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);
        	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
      
  2. 使能对BKPRTC的访问

    •   	//使能对BKP和RTC的访问
        	PWR_BackupAccessCmd(ENABLE);
      
  3. 开启LSE(外部低速时钟)时钟(RCC模块中)

  4. 配置RTCCLK数据选择器,指定LSERTCCLK的时钟源(RCC模块中)

  5. 等待:

    1. 前一次写操作结束
    2. 等待寄存器同步标志位被置位
  6. 配置PRL重装寄存器

  7. 配置CNT

  8. 选配闹钟和中断

MyRTC.c
#include "stm32f10x.h"                  // Device header

void MyRTC_Init(void)
{
	//开启电源(PWR)和备份寄存器(BKP)时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
	
	PWR_BackupAccessCmd(ENABLE);//使能对BKP和RTC的访问
	
	RCC_LSEConfig(RCC_LSE_ON);//开启LSE时钟
	while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == !SET);//等待LSE启动完成
	
	RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//指定LSE为RTC的时钟源
	RCC_RTCCLKCmd(ENABLE);//使能RTCCLK的时钟
	
	RTC_WaitForLastTask();//等待RTC上一个任务完成
	RTC_WaitForSynchro();//等待RTC同步
	
	RTC_SetPrescaler(32768 - 1);//(0~32767所以要减1)配置预分频器的值(32.768kHz/32768 = 1)
	RTC_WaitForSynchro();//写入寄存器时都需要等待RTC同步
	
	RTC_SetCounter(1735660800);//配置计数器CNT的值(时间戳)【2025-01-1 0:0:00】
	RTC_WaitForSynchro();//等待RTC同步
}

七、示例:实时时钟

①、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:    -  -");
	OLED_ShowString(2,1,"Time:  :  :");
	OLED_ShowString(3,1,"CNT :");
	OLED_ShowString(4,6,"DIV:");
	OLED_ShowHexNum(4,1, BKP_ReadBackupRegister(BKP_DR1), 4);
	
	struct tm* DATA;
    while(1)
    {
		DATA = MyRTC_Get_Time();
		
		OLED_ShowNum(1,6, DATA->tm_year + 1900,4);//年
		OLED_ShowNum(1,11,DATA->tm_mon + 1,2);		//月
		OLED_ShowNum(1,14,DATA->tm_mday,2);				//日
		OLED_ShowNum(2,6, DATA->tm_hour,2);				//时
		OLED_ShowNum(2,9, DATA->tm_min ,2);				//分
		OLED_ShowNum(2,12,DATA->tm_sec ,2);				//秒
		
		OLED_ShowNum(3,6,RTC_GetCounter(),10);
		OLED_ShowNum(4,10,RTC_GetDivider(),6);
    }
}

②、MyRTC.c

可通过设置Timestamp时间戳变量来设置系统时间

#include "stm32f10x.h"                  // Device header
#include "MyRTC.h"

#define TIME_ZONE_OFFSET (8 * 60 * 60)// 东八区时区偏移量(秒)

time_t Timestamp = 1735660780;//所设置时间的时间戳

void MyRTC_Init(void)
{
	//开启电源(PWR)和备份寄存器(BKP)时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);
	
	PWR_BackupAccessCmd(ENABLE);//使能对BKP和RTC的访问
	
	//加上if_else是为了防止重复初始化和时间重置
	if(BKP_ReadBackupRegister(BKP_DR1) != 0x1212)
	{
		RCC_LSEConfig(RCC_LSE_ON);//开启LSE时钟
		while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) != SET);//等待LSE启动完成
		
		RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//指定LSE为RTC的时钟源
		RCC_RTCCLKCmd(ENABLE);//使能RTCCLK的时钟
		
		RTC_WaitForSynchro();//等待RTC同步
		RTC_WaitForLastTask();//等待RTC上一个任务完成
		
		RTC_SetPrescaler(32768 - 1);//(0~32767所以要减1)配置预分频器的值(32.768kHz/32768 = 1)
		RTC_WaitForLastTask();//每一次写入操作都需要等待RTC上一个任务完成
		
//		RTC_SetCounter(1735660800);//配置计数器CNT的值(时间戳)【2025-01-1 0:0:00】
//		RTC_WaitForLastTask();//等待RTC上一个任务完成
		MyRTC_Set_Time();
		
		//在备份寄存器写入自己规定的标志位,用于判断RTC是不是第一次执行配置
		BKP_WriteBackupRegister(BKP_DR1, 0x1212);
	}
	else
	{
		RTC_WaitForSynchro();//等待RTC同步
		RTC_WaitForLastTask();//等待RTC上一个任务完成
	}
}

void MyRTC_Set_Time(void)//设置时间
{	
	RTC_SetCounter(Timestamp);//配置计数器CNT的值(时间戳)
	RTC_WaitForSynchro();//等待RTC同步
}

struct tm* MyRTC_Get_Time(void)//获取时间
{
	time_t time_cnt;
	time_cnt = RTC_GetCounter() + TIME_ZONE_OFFSET;//东八区 加上8天(即8*60*60秒)
	struct tm* Temp;
	Temp = localtime(&time_cnt);
	
	return Temp;
}

③、MyRTC.h

#ifndef __MYRTC_H__
#define __MYRTC_H__
#include "stdint.h"
#include <time.h>

extern time_t Timestamp;//所设置时间的时间戳

void MyRTC_Init(void);
void MyRTC_Set_Time(void);//设置时间
struct tm* MyRTC_Get_Time(void);//获取时间

#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2279415.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring的IoC、Bean、DI的简单实现,难度:※※※

目录 场景描述 第一步&#xff1a;初始化Maven项目 第二步&#xff1a;Maven导入Spring包&#xff08;给代码&#xff09; 第三步&#xff1a;创建Spring配置文件 第四步 创建Bean 第五步 简单使用Bean &#xff08;有代码&#xff09; 第六步 通过依赖注入使用Bean&…

Tensor 基本操作1 | PyTorch 深度学习实战

目录 创建 Tensor常用操作unsqueezesqueezeSoftmax代码1代码2代码3 argmaxitem 创建 Tensor 使用 Torch 接口创建 Tensor import torch参考&#xff1a;https://pytorch.org/tutorials/beginner/basics/tensorqs_tutorial.html 常用操作 unsqueeze 将多维数组解套&#xf…

自然语言处理——自注意力机制

一、文字表示方法 在自然语言处理中&#xff0c;如何用数据表示文字是基础问题。独热编码&#xff08;One-hot Encoding &#xff09;是一种简单的方法&#xff0c;例如对于 “我”“你”“他”“猫”“狗” 等字&#xff0c;会将其编码为如 “我 [1 0 0 0 0 ……]”“你 [0 …

嵌入式硬件篇---PID控制

文章目录 前言第一部分&#xff1a;连续PID1.比例&#xff08;Proportional&#xff0c;P&#xff09;控制2.积分&#xff08;Integral&#xff0c;I&#xff09;控制3.微分&#xff08;Derivative&#xff0c;D&#xff09;控制4.PID的工作原理5..实质6.分析7.各种PID控制器P控…

学成在线_内容管理模块_创建模块工程

学成在线模块工程 1.各个微服务依赖基础工程2.每个微服务都是一个前后端分离的项目3.xuecheng-plus-content&#xff1a;内容管理模块工程xuecheng-plus-content-modelxuecheng-plus-content-servicexuecheng-plus-content-api 1.各个微服务依赖基础工程 2.每个微服务都是一个前…

免费送源码:Java+ssm+MySQL Springboot卫生院儿童预防接种系统 计算机毕业设计原创定制

摘 要 儿童预防接种工作实行网络信息化管理&#xff0c;是我国预防规划工作发展的需要。接种信息实行网络信息化不仅是预防接种工作步入了一个新的台阶&#xff0c;更重要的是解决了多年接种疫苗过程种&#xff0c;预防接种剂次不清&#xff0c;难以全程有效接种的问题&#x…

OSPF的LSA的学习研究

OSPF常见1、2、3、4、5、7类LSA的研究 1、拓扑如图&#xff0c;按照地址表配置&#xff0c;激活OSPF划分相关区域并宣告相关网段 2、1类LSA&#xff0c;每台运行了OSPF的路由器都会产生&#xff0c;描述了路由器的直连接口状况和cost 可以看到R1产生了一条router lsa&#xff0…

JAVA:MyBatis 缓存机制详解的技术指南

1、简述 MyBatis是Java开发中常用的持久层框架之一&#xff0c;通过面向对象的方式操作数据库。为了提高系统性能&#xff0c;MyBatis提供了两级缓存机制&#xff1a;一级缓存&#xff08;本地缓存&#xff09;和二级缓存&#xff08;全局缓存&#xff09;。本文将详细讲解MyB…

前后端分离的Java快速开发平台

采用SpringBoot3.x、Shiro、MyBatis-Plus、Vue3、TypeScript、Element Plus、Vue Router、Pinia、Axios、Vite框架&#xff0c;开发的一套权限系统&#xff0c;极低门槛&#xff0c;拿来即用。设计之初&#xff0c;就非常注重安全性&#xff0c;为企业系统保驾护航&#xff0c;…

数据结构:栈和队列详解(上)

一.栈 1.概念与结构&#xff1a; 栈&#xff1a;一种特殊的线性表&#xff0c;只允许在顺序表的一段插入和删除数据&#xff0c;进行插入和删除的一端叫做栈顶&#xff0c;另外一端则叫做栈底&#xff0c;而我们将在栈顶插入数据叫做压栈&#xff08;入栈或进栈&#xff09;&a…

初识go语言之指针用法

一、环境准备 安装go语言编译环境&#xff0c;官网地址&#xff1a;https://go.dev/dl/ 或者 https://golang.google.cn/dl/ 点击下载按提示安装即可 vscode 安装go语言扩展 测试 package mainimport "fmt"func main() {fmt.Println("Hello, World!") …

python(25) : 含有大模型生成的公式的文本渲染成图片并生成word文档(支持flask接口调用)

公式样例 渲染前 \[\sqrt{1904.615384} \approx 43.64\] 渲染后 安装依赖 pip install matplotlib -i https://mirrors.aliyun.com/pypi/simple/ requestspip install sympy -i https://mirrors.aliyun.com/pypi/simple/ requestspip install python-docx -i https://mirro…

国产文本编辑器EverEdit - 恢复最近的选区

1 恢复最近的选区 1.1 应用场景 如果用户选择了一些文本&#xff0c;特别是多选区选择&#xff0c;在选择的过程中出现失误&#xff0c;导致选区丢失&#xff0c;一般的做法是骂骂咧咧再选一次&#xff0c;使用EverEdit就没有这个烦恼&#xff0c;EverEdit内置了恢复最近的选区…

54,【4】BUUCTF WEB GYCTF2020Ezsqli

进入靶场 吓我一跳&#xff0c;但凡放个彭于晏我都不说啥了 提交个1看看 1 and 11 1# 还尝试了很多&#xff0c;不过都被过滤了&#xff0c;头疼 看看别人的WP 竟然要写代码去跑&#xff01;&#xff01;&#xff01;&#xff0c;不会啊&#xff0c;先用别人的代码吧&#xf…

【unity进阶篇】unity如何实现跨平台及unity最优最小包体打包方式(.NET、Mono和IL2CPP知识介绍)

考虑到每个人基础可能不一样&#xff0c;且并不是所有人都有同时做2D、3D开发的需求&#xff0c;所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】&#xff1a;主要讲解C#的基础语法&#xff0c;包括变量、数据类型、运算符、…

实力认证 | 海云安入选《信创安全产品及服务购买决策参考》

近日&#xff0c;国内知名安全调研机构GoUpSec发布了2024年中国网络安全行业《信创安全产品及服务购买决策参考》&#xff0c;报告从产品特点、产品优势、成功案例、安全策略等维度对各厂商信创安全产品及服务进行调研了解。 海云安凭借AI大模型技术在信创安全领域中的创新应用…

联想装系统后触摸板无法设置双指手势

我的一个电脑是联想小新air13&#xff0c;装Windows10系统后&#xff0c;没有找到设置触摸板手势的地方 也没有“装置设定值” 这个选项 经查询&#xff0c;需要去联想网站搜索驱动&#xff0c;下载了一个“Lenovo联想驱动管理” &#xff0c;更新了下触摸板驱动&#xff0c; …

ue5 制作,播放,停止动画蒙太奇

右键&#xff0c;动画蒙太奇 新建插槽 把默认插槽选择为&#xff0c;自己新建的插槽 然后拖一个动画进去 input换成玩家0 就可以接收键盘事件 pawn 自动控制玩家换成玩家0 找到动画蓝图 把它化成我们那边蒙太奇里面的槽 第三步&#xff1a;第三人称角色蓝图 按下F…

一文大白话讲清楚webpack基本使用——1——完成webpack的初步构建

文章目录 一文大白话讲清楚webpack基本使用——1——完成webpack的初步构建1. 先回忆webpack是个啥2. webpack四大核心2.1 Entry(入口)2.2 Output(输出)2.3 Loader(加载器)2.4 Plugin(插件) 3. 按部就班实现webpack3.1 初始化项目3.2 完成项目骨架搭建3.3 实现webpack构建 一文…

迁移学习-详解

一、fasttext工具介绍 1 fasttext介绍 1.1 fasttext作用 作为NLP工程领域常用的工具包, fasttext有两大作用: 进行文本分类 训练词向量 1.2 fasttext工具包的优势 正如它的名字, 在保持较高精度的情况下, 快速的进行训练和预测是fasttext的最大优势. fasttext优势的原因:…