12:STM32---RTC实时时钟

目录

一:时间相关

1:Unix时间戳

2: UTC/GMT

3:时间戳转化

二:BKP

1:简历

2:基本结构

三: RTC

1:简历

2: 框图

3:RTC基本结构

4:RTC操作注意

四:案例

A:读写备份寄存器

1:连接图

2: 步骤

 3: 代码 

B:实时时钟

1:连接图

2:函数介绍 

3:代码


一:时间相关

1:Unix时间戳

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

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

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

2: UTC/GMT

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

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

3:时间戳转化

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

二:BKP

1:简历

        BKP(Backup Registers)备份寄存器

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

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

        RTC引脚输出RTC校准时钟、RTC闹钟脉冲或者秒脉冲

        存储RTC时钟校准寄存器 用户数据存储容量:     

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

2:基本结构

        BKP处于后备区域,  后备区域的作用:  当VDD主电源掉电时,后备区域仍然可以由VBAT的备用电池供电;  当VDD主电源上电时,后备区域供电会由VBAT切换到VDD,  也就是主电源有电时,VBAT不会用到,这样可以节省电池电量

        BKP里主要有 : 数据寄存器、控制寄存器、状态寄存器和RTC时钟校准寄存器,       其中数据寄存器是主要部分,用来存储数据的,  每个数据奇存器都是16位的,   一个数据奇存器可以存2个字节,  对于小的来说里面有DR1、DR2、一直到、DR10一共10个数据寄存器;    对于大容量和互联型里面有DR11~DR42的数据寄存器

        可以从PC13位置的TAMPERS脚引入一个检测信号器, 当TAMPER产生上升沿或者下降沿时, 清除BKP所有的内容,以保证安全-----对应简历中的第三条

        时钟输出,  可以把RTC的相关时钟,  从PC13位置的RTC引脚输出出去,供外部使用,  其中,输出校准时钟时,  再配合这个校准寄存器,可以对RTC的误差进行校准

三: RTC

1:简历

        RTC(Real Time Clock)实时时钟

        RTC是一个独立的定时器,可为系统提供时钟和日历的功能 RTC和时钟配置系统处于后备区域,系统复位时数据不清零,VDD(2.0~3.6V)断电后可借助VBAT(1.8~3.6V)供电继续走时

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

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

        可选择三种RTC时钟源:     

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

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

                LSI振荡器时钟(40KHz)

2: 框图

3:RTC基本结构

        3个时钟,选择一个当作RTCCLK,  之后RTCCLK先通过预分频器,对时钟进行分频.

        余数寄存器(DIV) : 是一个自减计数器,存储当前的计数值.

        重装寄存器 : 是计数目标,决定分频值, 分频之后,得到1Hz的秒计数信号,  通向32位计数器一秒自增一次

        3个信号可以触发中断,  分别是秒信号、计数器溢出信号和闹钟信号,  三个信号先通过中断输出控制,  三个信号先通过中断输出控制,  使能的中断才能通向NVIC

4:RTC操作注意

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

                 设置RCC_APB1ENR的PWREN和BKPEN,使能PWR和BKP时钟     

                设置PWR_CR的DBP,使能对BKP和RTC的访问

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

        必须设置RTC_CRL寄存器中的CNF位,使RTC进入配置模式后,才能写入RTC_PRL、RTC_CNT、RTC_ALR寄存器--------其实这个操作在库函数中, 每个写奇存器的函数,  它都自动帮我们加上了这个操作, 所以我们就不用再单独调用代码,进入配置模式了

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

四:案例

A:读写备份寄存器

1:连接图

2: 步骤

  1: 设置RCC_APB1ENR的PWREN和BKPEN,使能PWR和BKP时钟     

  2: 设置PWR_CR的DBP,使能对BKP和RTC的访问

 3: 代码 

简单的实现BKP的功能 

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Key.h"void Key_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);
}uint8_t Key_GetNum(void)
{uint8_t KeyNum = 0;if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0){Delay_ms(20);while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0);Delay_ms(20);KeyNum = 1;}if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0){Delay_ms(20);while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0);Delay_ms(20);KeyNum = 2;}return KeyNum;
}/*执行以下操作将使能对BKP和RTC的访问:     1: 设置RCC_APB1ENR的PWREN和BKPEN,使能PWR和BKP时钟     2: 设置PWR_CR的DBP,使能对BKP和RTC的访问*/
uint16_t ArrayWrite[]={0x1234,0x5678};
uint16_t ArrayRead[2];
uint16_t KeyNum;
int main(void)
{	Key_Init();OLED_Init();//1: 设置RCC_APB1ENR的PWREN和BKPEN,使能PWR和BKP时钟     RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);//2: 设置PWR_CR的DBP,使能对BKP和RTC的访问PWR_BackupAccessCmd(ENABLE);OLED_ShowString(1,1,"W:");OLED_ShowString(3,1,"R:");while (1){KeyNum=Key_GetNum();if (KeyNum==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(3,3,ArrayRead[0],4);OLED_ShowHexNum(3,8,ArrayRead[1],4);}}

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

        1: 设置RCC_APB1ENR的PWREN和BKPEN,使能PWR和BKP时钟     

        2: 设置PWR_CR的DBP,使能对BKP和RTC的访问

B:实时时钟

1:连接图

2:函数介绍 

在stm32f10x_rcc.h的文件中-----时钟相关的函数

void RCC_LSEConfig(uint8_t RCC_LSE);

void RCC_LSICmd(FunctionalState NewState);

void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource);
 

void RCC_RTCCLKCmd(FunctionalState NewState)

RCC_LSEConfig : 配置外部低速时钟(LSE)

RCC_LSICmd : 配置内部低速时钟(LSI)

RCC_RTCCLKConfig: 这个函数用来选择RTCCLK的时钟源 ,  实际上就是配置PPT的数据选择器

RCC_RTCCLKCmd : 使能--开启或者关闭RTC时钟

时钟在选择完毕后 , 需要获取标志位,等待标志完成后在操作

	RCC_LSEConfig(RCC_LSE_ON);//选择外部低速时钟while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET);//LSE准备ok了

在stm32f10x_rcc.h的文件中-----获取标志位函数

FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG);

在stm32f10x_rtc.h的文件中-----进入RTC配置模式

void RTC_EnterConfigMode(void)

 这个函数作用: 置CRL的CNF为1,进入配置模式

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

在stm32f10x_rtc.h的文件中-----退出RTC配置模式

void RTC_ExitConfigMode(void)

作用 : 就是把CNF位清零 

在stm32f10x_rtc.h的文件中-----CNT计数器相关

uint32_t RTC_GetCounter(void)
 

void RTC_SetCounter(uint32_t CounterValue)

RTC_GetCounter :  获取RTC计数器值

RTC_SetCounter :  写入CNT的值

在stm32f10x_rtc.h的文件中-----预分频器

void RTC_SetPrescaler(uint32_t PrescalerValue)

 RTC_SetPrescaler : 写入预分频器的值----这个值会写入到预分频器的PRL重装寄存器中,  用来配置预分频器的分频系数

在stm32f10x_rtc.h的文件中-----写入闹钟的值

void RTC_SetAlarm(uint32_t AlarmValue)

在stm32f10x_rtc.h的文件中-----读取预分频器中的DIV余数寄存器

 uint32_t  RTC_GetDivider(void);

余数奇存器是一个自减计数器 ,  获取余数奇存器的值,一般是为了得到更细致的时间

在stm32f10x_rtc.h的文件中-----等待完成操作

void RTC_WaitForLastTask(void);

void RTC_WaitForSynchro(void);

RTC_WaitForLastTask : 等待上次操作完成 

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

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

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

3:代码

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "MYRTC.h"uint16_t MyRTC_Time[] = {2023, 1, 1, 23, 59, 55};
void MYRTC_init(void)
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);PWR_BackupAccessCmd(ENABLE);if(BKP_ReadBackupRegister(BKP_DR1)!=0xA5A5){//LSE的频率是32.768KHz,也就是32768HzRCC_LSEConfig(RCC_LSE_ON);//选择外部低速时钟while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET);//LSE准备ok了RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//配置RTC时钟RTCCLKRCC_RTCCLKCmd(ENABLE);//开启RTC时钟RTC_WaitForLastTask();//等待上次操作完成 RTC_WaitForSynchro();//等待同步时钟//写预分频器RTC_SetPrescaler(32768-1);RTC_WaitForLastTask();RTC_SetCounter(1672588795); //写入CNTRTC_WaitForLastTask();BKP_WriteBackupRegister(BKP_DR1,0xA5A5);}else{RTC_WaitForLastTask();//等待上次操作完成 RTC_WaitForSynchro();//等待同步时钟}}void MYRTC_Settime(void)
{//内部的定义typedef unsigned int time_t; /* date/time in unix secs past 1-Jan-70 */	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; //mktimer日期类型的时间数据类型--转化为--秒计数器数据类型RTC_SetCounter(time_cnt);//写入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;
}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);}
}

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

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

相关文章

Linux -- 使用多张gpu卡进行深度学习任务(以tensorflow为例)

在linux系统上进行多gpu卡的深度学习任务 确保已安装最新的 TensorFlow GPU 版本。 import tensorflow as tf print("Num GPUs Available: ", len(tf.config.list_physical_devices(GPU)))1、确保你已经正确安装了tensorflow和相关的GPU驱动,这里可以通…

【数据结构练习】链表面试题集锦二

目录 前言: 1.链表分割 2.相交链表 3.环形链表 4.环形链表 II 前言: 数据结构想要学的好,刷题少不了,我们不仅要多刷题,还要刷好题!为此我开启了一个必做好题锦集的系列,每篇大约5题左右。此…

“高级前端开发技术探索路由的使用及Node安装使用“

目录 引言1. Vue路由的使用2. VueNode.js的安装使用总结 引言 在当今互联网时代,前端开发技术日新月异,不断涌现出各种新的框架和工具。作为一名前端开发者,我们需要不断学习和探索新的技术,以提升自己的开发能力。本文将深入探讨…

【C# Programming】值类型、良构类型

值类型 1、值类型 值类型的变量直接包含值。换言之, 变量引用的位置就是值内存中实际存储的位置。 2、引用类型 引用类型的变量存储的是对一个对象实例的引用(通常为内存地址)。 复制引用类型的值时,复制的只是引用。这个引用非常小&#xf…

前后端分离毕设项目之产业园区智慧公寓管理系统设计与实现(内含源码+文档+教程)

博主介绍:✌全网粉丝10W,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业毕业设计项目实战6年之久,选择我们就是选择放心、选择安心毕业✌ 🍅由于篇幅限制,想要获取完整文章或者源码,或者代做&am…

短视频抖音账号矩阵系统源码开发者自研(四)

抖音是一款备受欢迎的短视频APP,拥有数亿的用户,其中包括了大量的粉丝。为了让更多的人能够发现和观看到你的视频,抖音SEO是必不可少的一环,特别是对于拥有企业或个人品牌的用户来说。在这个过程中,抖音SEO源码的开源部…

SQL注入脚本编写

文章目录 布尔盲注脚本延时注入脚本 安装xampp,在conf目录下修改它的http配置文件,如下,找到配置文件: 修改配置文件中的默认主页,让xampp能访问phpstudy的www目录,因为xampp的响应速度比phpstudy快得多&am…

Linux C 网络基础

为什么需要网络通信? 进程间通信解决的是本机内通信 网络通信解决的是任意不同机器的通信 实现网络通信需要哪些支持 1.通信设备:网卡(PC机自带); 路由器和交换机; 光纤…

在Scrapy框架中使用隧道代理

今天我要和大家分享一些实战经验,教你如何在Scrapy框架中使用隧道代理。如果你是一个热爱网络爬虫的开发者,或者对数据抓取和处理感兴趣,那么这篇文章将帮助你走上更高级的爬虫之路。 首先,让我们简单介绍一下Scrapy框架。Scrapy…

【计算机网络】——应用层

// 图片取自王道 仅做交流学习 一、基本概念 应用层概述 协议是 网络层次模型 中多台主机之间 同层之间进行通信的规则。是一个水平概念 垂直空间上,向下屏蔽下层细节,向上提供服务接入,多台主机之间同层之间形成一条逻辑信道。 应用层的…

编译ctk源码

目录 前景介绍 下载The Common Toolkit (CTK) cmake-gui编译 vs2019生成 debug版本 release版本 前景介绍 CTK(Common Toolkit)是一个用于医学图像处理和可视化应用程序开发的工具集,具有以下特点: 基于开源和跨平台的Qt框…

Spring 6.0 新特性

文章目录 Spring的发展历史AOTGraalVMSpringBoot实战AOTRuntimeHints案例分析RuntimeHintsRegistrar SpringBoot中AOT核心代码 Spring的发展历史 AOT Spring 6.0的新特性Ahead of Time(AOT)编译是一种技术,可以提前将Spring应用程序编译成原…

【SpringCloud】微服务技术栈入门1 - 远程服务调用、Eureka以及Ribbon

目录 远程服务调用RestTemplate Eureka简要概念配置 Eureka 环境设置 Eureka ClientEureka 服务发现 Ribbon工作流程配置与使用 Ribbon饥饿加载 远程服务调用 RestTemplate RestTemplate 可以模拟客户端来向另外一个后端执行请求 黑马给出的微服务项目中,有两个 …

yolov5使用最新MPDIOU损失函数,有效和准确的边界盒回归的损失,优于GIoU/EIoU/CIoU/EIoU(附代码可用)

文章目录 1. 论文1.1. 主要目的1.2. 设计思路2 代码3.总结1. 论文 MPDIoU: A Loss for Efficient and Accurate Bounding Box Regression (一个有效和准确的边界框损失回归函数) 论文地址 1.1. 主要目的 当预测框与边界框具有相同的纵横比,但宽度和高度值完全不同时,大多数…

20230918使用ffmpeg将mka的音频转为AAC编码以便PR2023来识别

20230918使用ffmpeg将mka的音频转为AAC编码以便PR2023来识别 2023/9/18 20:58 ffmpeg -i 1.mka -acodec aac 1.mp4 ffmpeg -i 1.mka -vn -c:a aac 2.aac ffmpeg -i 1.mka -vn -c:a aac 2.MP4 ffmpeg mka 转 aacmp4 https://avmedia.0voice.com/?id42526 用ffmpeg将mka格式转化…

云端IDE的技术选型1

背景 考虑到以下几点,准备给低代码平台开发一套云端的IDE: 桌面端IDE:vs code 或 idea,都有需要开发人员安装ide,以及配置环境很多时候,配置开发环境是个非常曲折过程,经常出现版本不匹配&…

【分布式计算】副本数据Replicated Data

作用:可靠性、高性能、容错性 问题:如何保持一致、如何更新 问题:存在读写/写写冲突 一个简单的方法就是每个操作都保持顺序,但是因为网络延迟会导致问题 Data-centric models: consistency model?? ??? 读取时&#xff0c…

深入理解WPF中MVVM的设计思想

近些年来,随着WPF在生产,制造,工业控制等领域应用越来越广发,很多企业对WPF开发的需求也逐渐增多,使得很多人看到潜在机会,不断从Web,WinForm开发转向了WPF开发,但是WPF开发也有很多…

图像处理软件Photoshop 2024 mac新增功能

Photoshop 2024 mac是一款图像处理软件的最新版本。ps2024提供了丰富的功能和工具,使用户能够对照片、插图、图形等进行精确的编辑和设计。 Photoshop 2024 mac软件特点 快速性能:Photoshop 2024 提供了更快的渲染速度和更高效的处理能力,让用…

MyBatis 缓存模块

文章目录 前言缓存的实现Cache接口PerpetualCache 缓存的应用缓存对应的初始化一级缓存二级缓存第三方缓存 前言 MyBatis作为一个强大的持久层框架,缓存是其必不可少的功能之一,Mybatis中的缓存分为一级缓存和二级缓存。但本质上是一样的,都…