STM32G070KBT6的RTC HAL库使用

news2024/9/23 19:28:45

*配置问题

    首先使能时钟源,这里在时钟配置中选择LSI,为什么后面会说,然后使能Calender结构体,保证可以对RTC的年月日时分秒等进行写入和读取;alarmA和alarmB是闹钟,这里不用就Disable;      Tamper用于检测外部篡改事件(通常用于增强系统的安全性,尤其是在需要保护敏感数据或防止恶意操作的应用中。),使能后会有一个专用引脚,Timestamp是时间戳,使能后会出现一个引脚,当该引脚检测到篡改事件时,可以触发中断或其他响应机制(例如自动清除 RTC 的备份寄存器,以防止敏感数据被读取或篡改。)同时RTC 备份域中的特定寄存器可以记录篡改事件的发生,以便后续分析和处理。

    TimeStamp功能允许在特定事件发生时,记录当前的日期和时间。这对于需要精确记录事件发生时间的应用非常有用。使能后同样会有一个专用引脚,可以记录按钮按下、外部中断、篡改检测等事件的时间,在数据记录系统(RTC 备份域)中,可以为每条记录添加时间戳,以便后续分析。

    Calibration使能后也有一个专用引脚,用于对外输出特定频率的脉冲,外部可以通过该引脚输出的脉冲判断RTC的精度;

    根据我们选择的功能,我们需要配置上述参数,首先Asynchronous Predivider value和Synchronous Predivider value用于将RTC的时钟分频,我们一般进行秒级计数,所以将其分频到1HZ,计算方法为:时钟源频率/(Asynchronous Predivider value+1)/(Synchronous Predivider value),这里为32.768KHZ/128/256 = 1HZ;  

    Day Light Saving和Store Operation分别代表夏令时和重置存储操作,夏令时是一种为了节约能源而对时钟进行调整的制度。在夏令时期间,时钟会提前一小时,以便在白天更长的时间内利用自然光。夏令时的设置可以帮助设备自动调整时间以适应这种变化。我们一般不开启夏令时以保证RTC的时间是标准时间;重置存储操作:

  • RTC_STOREOPERATION_RESET:在低功耗模式下不存储当前时间设置,退出低功耗模式时时间会被重置。
  • RTC_STOREOPERATION_SET:在低功耗模式下保存当前时间设置,退出低功耗模式时恢复到之前的时间。

    我们一般选择RTC_STOREOPERATION_SET,这样就算进入和退出低功耗模式,RTC时间仍然会保持计数;

    Wake UP用于设置RTC唤醒中断,其中的Wake UP Clock是唤醒中断周期,设置为1HZ唤醒中断周期就是1秒,Wake Up Counter就是经过n+1次唤醒中断周期后触发中断,这里n为0,表示经过1次唤醒中断周期,也就是1秒后触发中断;

    Data Format分为BCD格式和BIN格式,BIN格式十进制数12表示0x0C,和我们正常的二进制-十进制转换相同,BCD格式是一种将每个十进制数的每一位用四位二进制表示的方法,十进制数12表示为0x12;一般我们用BIN格式更符合常识;

HAL_RTC_GetTime()和HAL_RTC_SetTime()用于获取和设置RTC的时分秒;

HAL_RTC_GetDate()和HAL_RTC_SetDate()用于获取和设置RTC的年月日星期;

注意上面的函数执行时要有顺序!读取时间时先执行HAL_RTC_GetTime()再执行HAL_RTC_GetDate(),不然就会导致读取时间无效的情况;同样设置时间先HAL_RTC_SetDate()再HAL_RTC_SetTime();代码例子如下:

RTC_Time.c:

#include "RTC_Time.h"

/**
  * @brief	时间设置
  * @param   
  *		@arg 	分别输入 年 月 日 星期 时 分 秒
  * @retval 无
  */
void RTC_SetTime(uint16_t yea,uint8_t mon,uint8_t da, uint8_t hou,uint8_t min,uint8_t sec)
{
	  RTC_TimeTypeDef RTC_Time;
    RTC_DateTypeDef RTC_Date;
	
		system_config.calendar.year = yea;
		system_config.calendar.century = yea/100;
		system_config.calendar.month = mon;
		system_config.calendar.date = da;
		system_config.calendar.hour = hou;
		system_config.calendar.min = min;
		system_config.calendar.sec = sec;
		system_config.calendar.week = GregorianDay(system_config.calendar);
	  Flash_WriteStruct(FLASH_USER_START_ADDR, &system_config);            //将系统配置保存到FLASH用户数据区
	
	
	  RTC_Date.Year = (uint8_t)(system_config.calendar.year%100);    //RTC中year格式为uint8_t,我们这里用其保存年份后两位
	  RTC_Date.Month = system_config.calendar.month;
	  RTC_Date.Date = system_config.calendar.date;
	  RTC_Date.WeekDay = system_config.calendar.week;
	
	  RTC_Time.Hours = system_config.calendar.hour;
		RTC_Time.Minutes = system_config.calendar.min;
	  RTC_Time.Seconds = system_config.calendar.sec;
	  RTC_Time.DayLightSaving = DayLightSaving_status;
	  RTC_Time.StoreOperation = StoreOperation_status;
	
	
	  HAL_RTC_SetDate(&hrtc, &RTC_Date, RTC_FORMAT_BIN);      //将配置写入到RTC
	  HAL_RTC_SetTime(&hrtc, &RTC_Time, RTC_FORMAT_BIN);
}

/**
  * @brief	获取时间
  * 
  *		
  */
void RTC_GetTime(void)
{
	  RTC_TimeTypeDef RTC_Time;
    RTC_DateTypeDef RTC_Date;
	
	  HAL_RTC_GetTime(&hrtc, &RTC_Time, RTC_FORMAT_BIN);   //先运行GetTime再运行GetDate
	  HAL_RTC_GetDate(&hrtc, &RTC_Date, RTC_FORMAT_BIN);
   
	
	  system_config.calendar.year = system_config.calendar.century*100 + RTC_Date.Year;  //将Flash中的世纪和RTC中的年份相加获得完整年份
		system_config.calendar.month = RTC_Date.Month;
		system_config.calendar.date = RTC_Date.Date;
	  system_config.calendar.week = RTC_Date.WeekDay;
	
		system_config.calendar.hour = RTC_Time.Hours;
		system_config.calendar.min = RTC_Time.Minutes;
		system_config.calendar.sec = RTC_Time.Seconds;
	  //Flash_WriteStruct(FLASH_USER_START_ADDR, &system_config);            //将系统配置保存到FLASH用户数据区
}




void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{
  /* Prevent unused argument(s) compilation warning */
   	
	
	//HAL_IWDG_Refresh(&hiwdg);   //喂狗,5s内必须喂一次
		RTC_GetTime();   	//更新时间   
		Write_Num_Time();							  //显示时间
  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_RTCEx_WakeUpTimerEventCallback could be implemented in the user file
   */
}



/*计算公历天数得出星期*/
static int GregorianDay(_calendar_obj tm)
{
	int leapsToDate;
	int lastYear;
	int day;
	int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
 
	lastYear=tm.year-1;
 
	/*计算从公元元年到计数的前一年之中一共经历了多少个闰年*/
	leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;      
 
     /*如若计数的这一年为闰年,且计数的月份在2月之后,则日数加1,否则不加1*/
	if((tm.year%4==0) &&
	   ((tm.year%100!=0) || (tm.year%400==0)) &&
	   (tm.month>2)) {
		/*
		 * We are past Feb. 29 in a leap year
		 */
		day=1;
	} else {
		day=0;
	}
 
	day += lastYear*365 + leapsToDate + MonthOffset[tm.month-1] + tm.date; /*计算从公元元年元旦到计数日期一共有多少天*/
 
	tm.week=day%7; //算出星期
	if(tm.week == 0) 
		tm.week = 7;
	return tm.week;
}
 

RTC_Time.h:

#ifndef __RTC_TIME_H__
#define __RTC_TIME_H__


#include "main.h"
#include "User_Flash.h"
#include "rtc.h"
#include "74HC595.h"

#define DayLightSaving_status     RTC_DAYLIGHTSAVING_NONE   //配置RTC夏令时状态
#define StoreOperation_status     RTC_STOREOPERATION_SET    //配置RTC 是否在低功耗模式保持运行

void RTC_SetTime(uint16_t yea,uint8_t mon,uint8_t da, uint8_t hou,uint8_t min,uint8_t sec);
void RTC_GetTime(void);
static int GregorianDay(_calendar_obj tm); 
#endif


*电源引脚问题:

    从上图我们可以看出LQFP32封装的G070KBT6是没有VBAT引脚的,只有VDD引脚,因此当主电源VDD断电后采用电池给VDD供电,因此RTC也只能由VDD保持供电,可以用一路ADC采样主电源电压,当检测到主电源电压接近0V时表示此时已切换到电池供电,然后进行相应操作。电路如下:

    巧思:要做低功耗,可以进入低功耗就把检测电源电压的ADC转化为外部中断,当再次上电时触发外部中断退出低功耗模式,这样就不用电池供电的时候还要用ADC检测电源是否重新上电,节省功耗。(未验证)

*时钟源问题 :

    只有一个外部高速时钟,可以选择LSI或者HSE/32(一般RTC外部时钟源可以选择LSE或者HSE,通常使用LSE,不过为了节省晶振的情况下也可以用HSE分频替代,这样也比LSI更稳定。),由于主电源断电之后采用外部高速时钟HSE为有源晶振,会停止起振,因此这里使用LSI内部低速32.768KHZ晶振给RTC提供时钟源。由前面关于RTC的手册描述我们可以知道当LSI计时时,VBAT模式下RTC是不工作的,因为vbat只能给LSE供电而不能给LSI供电。vdd断了以后LSI也相当于断电了,rtc自然就不走了。但是由于G070KBT6没有VBAT引脚,因此也就没有VBAT模式,就算用刚刚的电池供电也是给VDD供电,因此这里不用担心电池供电时RTC会停止工作。

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

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

相关文章

突破•指针六

听说这是目录哦 数组和指针笔试题解析🫧一维数组1🍕🍕🍕🍕🍕🍕🍕 字符数组1🍔🍔🍔🍔🍔🍔🍔2&#…

高并发下的分布式缓存 | Read-Through缓存模式

缓存系列文章链接如下: 高并发下的分布式缓存 | 缓存系统稳定性设计 高并发下的分布式缓存 | 设计和实现LRU缓存 高并发下的分布式缓存 | 设计和实现LFU缓存 高并发下的分布式缓存 | Cache-Aside缓存模式 Read-Through 模式的缓存操作 Read-Through模式的一个关键…

Scanner类、String类和StringBuffer类的相关使用

一、Scanner: 主要用于键盘录入的 构造方法: Scanner(InputStream source) 构造一个新的 Scanner ,产生从指定输入流扫描的值。 1、next()和nextLine()区别: String line sc.next(); // 不会接收特殊字符,比如空格回…

高效的编程学习方法和技巧

编程小白如何成为大神?大学新生的最佳入门攻略 编程已成为当代大学生的必备技能,但面对众多编程语言和学习资源,新生们常常感到迷茫。如何选择适合自己的编程语言?如何制定有效的学习计划?如何避免常见的学习陷阱&…

基于单片机的智能空气净化系统

【摘 要】 设计了一种基于单片机的智能空气净化系统。通过传感器实时采集空气中 PM2.5 、甲醛等有害健康物质的浓度,将各项数据显示到液晶显示屏,当浓度超过设置的警戒值时,控制蜂鸣器发出警报。根据浓度大小控制空气净化器电机转速&#xf…

04.C++类和对象(中)

1.类的默认成员函数 默认成员函数就是用户没有显式实现,编译器会自动生成的成员函数称为默认成员函数。一个类,我们不写的情况下编译器会默认生成以下6个默认成员函数,需要注意的是这6个中最重要的是前4个,最后两个取地址重载不重…

Selenium + Python 自动化测试04(操作方法1)

上一篇我们讲述了webdriver 元素定位方法。我们对如何定位元素有了一个基本的认识。接着我们详细讲述对元素常见的一些基本操作方法,以便我们可以做很多功能操作的测试。这一篇侧重最基本的操作方面。 1、send_keys 方法 此方法类似于模拟键盘输入。还是以下面网站…

React项目中引用视频播出插件 easyPlayer.js 部署趟坑日志

目录 前文记录背景问题摸排:第一天前端打包失败?远程打包逻辑与本地打包逻辑不一致?远程入口页被篡改?再次排查本地webpack打包逻辑 问题摸排:第二天确认本地与远程打包一致排查远程nginx代理定位问题 index.html 的所…

AI10-PaddleDetection2.7安装测试

1、下载PaddleDetect-release-2.7开源项目 https://github.com/PaddlePaddle/PaddleDetection https://github.com/PaddlePaddle/PaddleDetection/releases PaddleDetection: PaddleDetection的目的是为工业界和学术界提供丰富、易用的目标检测模型 2、安装 环境要求 * Paddl…

[Qt][QWidget]详细讲解

目录 1.概述2.QWidget核心属性1.简介2.核心属性概览 3.QWidget常用属性1.enabled2.geometry1.是什么?2.Window Frame的影响3.相关API4.注意 3.windowTitile4.windowIcon5.windowOpacity6.cursor8.font9.toolTip10.focusPolicy11.styleSheet 1.概述 Widget是Qt中的核…

2024新版ChatGPT系统源码SparkAi系统,支持GPT4.0全模型,AI绘画,AI换脸+自定义智能体GPTs应用+AI视频+文档分析

一、文章序言 人工智能技术正迅猛发展,AI语言模型、AI绘画和AI视频已经在许多领域得到广泛应用。这些技术不仅在科技创新方面表现出色,还在艺术创作、内容生成和商业应用中展现出巨大的潜力。 SparkAi创作系统是一款基于ChatGPT和Midjourney开发的智能…

【Linux】系列入门摘抄笔记-4-查看文件内容命令cat/more/less/tail

cat 查看文件内容 cat [选项] [参数] cat 命令可以用来显示文本文件的内容(类似于 DOS 下的 type 命令),也可以把几个文件内容附加到另一个文件中,即连接合并文件。 tac 反向显示文件内容 tac [选项] [参数] 将文件全部内容从…

玩转Docker:Lsky pro图床+私有化部署大模型(Ollama+Openwebui)

最近搞了一个测试服务器,捣鼓了下一键搭建dnmp集成环境,然后还搭建了一个Lysk pro图床服务,后面又看到了开源大模型,也试着搭建了一下,中间出了一点小插曲。不过也算搭建成功了。做一个小结汇总。 1.前情回顾 DNMP:基…

探索list与iterator的区别及yield的用法

1 问题 探索list与iterator的区别探索yield的用法 2 方法 通过网上学习后了解到 List返回的类型是list,list只会查询一级缓存。list()中返回的List中每个对象都是原本的对象。查询的时候没遍历一个对象会产生一条sql;而iterator这个迭代器返回的类型是it…

Apache HTTPD 换行漏洞(CVE-2017-15715)

Vulhub - Docker-Compose file for vulnerability environment Apache HTTPD是一款HTTP服务器,它可以通过mod_php来运行PHP网页。其2.4.0~2.4.29版本中存在一个解析漏洞,在解析PHP时,1.php\x0A将被按照PHP后缀进行解析,导致绕过一…

sns.distplot()用法

seaborn.distplot(aNone, binsNone, histTrue,kdeTrue, rugFalse, fitNone, hist_kwsNone,kde_kwsNone, rug_kwsNone, fit_kwsNone,colorNone, verticalFalse, norm_histFalse,axlabelNone, labelNone, axNone, xNone)参数解释 a: 序列series、一维数组或者list,上…

经典街机游戏:拳皇97 for Mac(KOF97) 支持M1 中文移植版

游戏玩家一定会上手的游戏就是拳皇系列了吧,其中最经典的就是拳皇97,小编为大家提供的就是拳皇97mac版,熟悉的场景,熟悉的操作,原来Mac上打街机也可以这么爽,亲测拳皇97 for Mac 支持M1 Mac,喜欢…

ASP.NET Core Web API 使用Autofac框架

总目录 前言 主要介绍如何在ASP.NET Core Web API 使用Autofac框架 一、创建ASP.NET Core Web API 我们先创建一个ASP.NET Core Web API项目,然后准备相关的代码 1 假如我们需要实现登录的功能,现在我们创建相关的服务接口 public interface ILoginSe…

【vue+mathjax】mathjax的使用

方法一、引用外网的地址 但是使用这个方法&#xff0c;会报跨域&#xff0c;所以需要注意 第一步&#xff1a;在public/index.html中引入地址 <!DOCTYPE html> <html><head><meta charset"utf-8" /><meta http-equiv"X-UA-Compatib…

【uniapp】uniapp+vue2微信小程序实现分享功能

uniappvue2做的微信小程序实现分享功能 问题描述 uniappvue2做的微信小程序&#xff0c;发布以后点击右上角三个点&#xff0c;分享小程序的时候&#xff0c;转发和分享按钮都是灰色 解决方案 转发、分享、复制链接这几个功能需要自己来手动写方法&#xff0c;考虑到每个页…