当前位置: 首页 > news >正文

STM32--RTC实时时钟

文章目录

  • Unix时间戳
  • 时间戳转换
  • BKP
  • RTC简介
  • RTC框图
  • 硬件电路
  • RTC的注意事项
  • RTC时钟实验工程

Unix时间戳

Unix 时间戳是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒

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

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

在这里插入图片描述

GMT : GMT(Greenwich Mean Time), 格林威治平时(也称格林威治时间)。
它规定太阳每天经过位于英国伦敦郊区的皇家格林威治天文台的时间为中午12点。它将地球自转一周的时间间隔等分为24小时,以此确定计时标准。

UTC:UTC(Coodinated Universal Time),协调世界时,又称世界统一时间、世界标准时间、国际协调时间。
UTC 是现在全球通用的时间标准,全球各地都同意将各自的时间进行同步协调。UTC 时间是经过平均太阳时(以格林威治时间GMT为准)、地轴运动修正后的新时标以及以秒为单位的国际原子时所综合精算而成。

时间戳转换

对于我们目前使用的电子设备,都是通过联网来确认时间戳的。所以我们看到的时间都是由时间戳转换成日期的。

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

在这里插入图片描述
这里讲几个会用到的。

第一个,time_t time(time_t*),获取系统时钟。
通过使用设备当前时间,获取一个时间戳。
在这里插入图片描述

第二个,struct tm* gmtime(const time_t*);秒计数器转换为日期时间(格林尼治时间)
在这里插入图片描述
这里需要注意的是struct tm 结构体类型成员year和mon
在这里插入图片描述
年是从1900年算起的,所以实际时间要加上1900;
月是从0开始的,所以要加上1;
时是由于计算是标准时间,所以要加上8才是东八区的标准时间。

第三个,time_t mktime(struct tm*);日期时间转换为秒计数器(当地时间)
在这里插入图片描述

由于STM32无法计算系统时钟,需要软件输入设置当前时间,所以也没有当地时间与标准时间的概念。

在这里插入图片描述

BKP

备份寄存器是42个16位的寄存器,可用来存储84个字节的用户应用程序数据。(对于中小容量的产品,只能存储20个字节)他们处在备份域里,当VDD电源被切断,他们仍然由VBAT维持供电。当系统在待机模式下被唤醒,或系统复位或电源复位时,他们也不会被复位。
也就是说,只要有一方供电,保存的数据就不会丢失;

BKP控制寄存器用来管理侵入检测和RTC校准功能

在这里插入图片描述

侵入检测:当TAMPER引脚上的信号从’0’变成’1’或者从’1’变成’0’(取决于备份控制寄存器BKP_CR的TPAL位),会产生一个侵入检测事件。侵入检测事件将所有数据备份寄存器内容清除
RTC校准:为方便测量, RTC时钟可以经64分频输出到侵入检测引脚TAMPER上。
这里只是简单介绍这两种功能而已。
在这里插入图片描述

RTC简介

实时时钟是一个独立的定时器RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。
RTC模块和时钟配置系统(RCC_BDCR寄存器)处于后备区域,即在系统复位或从待机模式唤醒后, RTC的设置和时间维持不变。
在这里插入图片描述
操作访问方法与BKP相同。

相关特性
在这里插入图片描述

RTC框图

在这里插入图片描述
RTC时钟部分就是在后备区域内,上面连接着APB1总线进行读写的操作,
左边连接着RTC时钟源。
RTC核心部分是完全独立于APB接口的,需要通过软件,经过APB1接口访问RTC的预分频值,计数器值和闹钟值。
RTC预分频器会先预装重装载器,然后给到DIV,在RTCCLK时钟源进来的每一次,DIV以递减的方式,直到DIV为0时才将输出时钟传到CNT上;
CNT是一个计数器,用来存储时间戳;下面的ALR是闹钟寄存器,当CNT与ALR相等时,可以通过闹钟来产生中断;
这些产生的时钟信号经过控制寄存器进入NVIC中断控制器。
在这里插入图片描述

硬件电路

在这里插入图片描述
这部分是备用电池供电的电路,对于简单连接的就是直接连上一个3.3V供电的即可。
右边的是纽扣电池的连接方式。

在这里插入图片描述
外部低速晶振图,外部时钟的产生;
在这里插入图片描述

RTC的注意事项

执行以下操作将使能对BKP和RTC的访问:
设置RCC_APB1ENR的PWREN和BKPEN,使能PWR和BKP时钟
设置PWR_CR的DBP,使能对BKP和RTC的访问(开启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寄存器

RTC时钟实验工程

OLED代码链接入口

连接方式:
在这里插入图片描述
在OLED屏幕显示一个实时时钟;

MyRTC.h

#ifndef __MYRTC_H__
#define __MYRTC_H__#include "stm32f10x.h"                  // Device header
#include <time.h>typedef struct Time
{int sec;int min;int hour;int mday;int mon;int year;}Time;void MyRTC_Init(Time* t);
void MyRTC_SetTime(Time* t);
void MyRTC_ReadTime(Time* t);#endif

MyRTC.c

#include "MyRTC.h"//时间设置
void MyRTC_SetTime(Time* t)
{time_t time_cnt;//计数器struct tm time_date;//时钟日期time_date.tm_year=  t->year-1900;time_date.tm_mon= t->mon-1;time_date.tm_mday= t->mday;time_date.tm_hour= t->hour;time_date.tm_min= t->min;time_date.tm_sec= t->sec;//设置计数器//日期转换为时间戳time_cnt=mktime(&time_date)-8*60*60;RTC_SetCounter(time_cnt);RTC_WaitForLastTask();   
}void MyRTC_Init(Time* t)
{//打开电源和后备接口的时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);//开启RTC的使用PWR_BackupAccessCmd(ENABLE);// if(BKP_ReadBackupRegister(BKP_DR1)!=0x1111)// {//配置LSERCC_LSICmd(ENABLE);while(!RCC_GetFlagStatus(RCC_FLAG_LSIRDY));//RCCLK选择LSERCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);//开启RTC的时钟源RCC_RTCCLKCmd(ENABLE);//时钟同步  RTC_WaitForSynchro();RTC_WaitForLastTask();//设置分频器,写操作等待完成RTC_SetPrescaler(32767);RTC_WaitForLastTask();//时间初始化设置MyRTC_SetTime(t);//非首次和完全断电给一个值//     BKP_WriteBackupRegister(BKP_DR1,0x1111);//  }// else// {//     RTC_WaitForSynchro();//     RTC_WaitForLastTask();// }}//读取时间
void MyRTC_ReadTime(Time* t)
{time_t time_cnt;//计数器struct tm time_date;//时钟日期//时间戳转换为日期time_cnt=RTC_GetCounter()+8*60*60;time_date=*localtime(&time_cnt);t->year=time_date.tm_year+1900;t->mon=time_date.tm_mon+1;t->mday=time_date.tm_mday;t->hour=time_date.tm_hour;t->min=time_date.tm_min;t->sec=time_date.tm_sec;
}

对于时钟的选择内部时钟LSI无法在断开电源和复位时进入后备区域;LSE外部时钟可以,我们可以设置一个值,只要是这个值说明就进入了后备区域。由于我的外部时钟晶振无法震荡,所以只能使用内部时钟,读者可以
修改为在这里插入图片描述
并将那些注释解开即可。
这里进行写操作时,函数中就已经进入了配置模式了
在这里插入图片描述
这里输入的时钟是东八区的时间,而设置计数器为标准时间的时间戳,所以要进行减去8* 60* 60
等到读取时间时再加回来

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "MyRTC.h"int main()
{Time time;time.year=2023;time.mon=1;time.mday=1;time.hour=23;time.min=59;time.sec=55;OLED_Init();MyRTC_Init(&time);MyRTC_SetTime(&time);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(&time);OLED_ShowNum(1, 6, time.year, 4);OLED_ShowNum(1, 11,time.mon, 2);OLED_ShowNum(1, 14, time.mday, 2);OLED_ShowNum(2, 6, time.hour, 2);OLED_ShowNum(2, 9, time.min, 2);OLED_ShowNum(2, 12, time.sec, 2);OLED_ShowNum(3, 6, RTC_GetCounter(), 10);OLED_ShowNum(4, 6, RTC_GetDivider(), 10);}}
http://www.lryc.cn/news/157610.html

相关文章:

  • 【N2】例题学习笔记
  • 【数据分享】2006-2021年我国城市级别的道路、桥梁、管线建设相关指标(10多项指标)
  • 视觉SLAM14讲笔记-第7讲-视觉里程计2
  • MySQL——单行函数和分组函数
  • 百度百科词条怎么更新?怎么能顺利更新百科词条?
  • PPT怎么转换为PDF格式,收藏这两个在线工具。
  • 八大排序算法----堆排序
  • Docker Desktop 设置镜像环境变量
  • springboot之一:配置文件(内外部配置优先顺序+properties、xml、yaml基础语法+profile动态切换配置、激活方式)
  • 涛然自得周刊(第 5 期):蝲蛄吟唱的地方
  • Android Ble蓝牙App(七)扫描过滤
  • 小程序当前页面栈以及跳转
  • jQuery获取表单的值val()
  • 【专栏必读】数字图像处理(MATLAB+Python)专栏目录导航及学习说明
  • 2023年非证券类投资银行业发展报告
  • Matlab 如何把频谱图的纵坐标设置为分贝刻度
  • VUE写后台管理(2)
  • RHCSA8.2
  • 修改linux中tomcat的端口
  • 学妹学Java(一)
  • 湖南省副省长秦国文一行调研考察亚信科技
  • k8s部署redis 3主3从
  • Vue2安装vuex和vue-router报错处理
  • 算法leetcode|79. 单词搜索(rust重拳出击)
  • 2023年高教社杯全国大学生数学建模竞赛参赛事项注意
  • 数学建模--逻辑回归算法的Python实现
  • Qt6_贪吃蛇Greedy Snake
  • Credo推出业界首款单片集成CMOS VCSEL驱动器的800G光DSP芯片
  • 【经验分享】如何使用VSCode对比两个文件
  • 从裸机开始安装ubuntu系统到安装NVIDIA驱动