合泰杯(HT32F52352)RTC的应用(计时)--->掉电不丢失VBAT(代码已经实现附带源码)

本文主要是介绍合泰杯(HT32F52352)RTC的应用(计时)--->掉电不丢失VBAT(代码已经实现附带源码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

     摘要

         在HT32F52352合泰单片机开发中,rtc在网上还是挺少人应用的,找了很久没什么资料,现在我根据手册和官方的代码进行配置理解。 RTC在嵌入式单片机中是一个很重要的应用资源。

  1. 记录事件时间戳:RTC可以记录事件发生的精确时间,方便后续分析和追溯。

  2. 定时操作:通过RTC可以实现定时操作,例如定时采集数据、定时发送信息等。

  3. 时间相关功能:RTC可以提供当前的日期和时间信息,方便系统中进行时间相关的业务逻辑。

  4. 实时显示:RTC可以在设备上实时显示当前的时间,方便用户查看。

  5. 节能功能:通过RTC可以实现设备定时开关机等节能功能,提高设备的能效。


介绍        

        我们在做项目的时候,要用到时间计时,我们刚开始用的定时器,这个比较简单,但是后来我们想到一个问题就是如果我们芯片如果卡死复位了,掉电了,那么我们整一个流程中计时功能又从头开始。基于严谨考虑我觉得使用芯片另一个芯片资源符合我要求的就是rtc时钟。怎么用呢,下面按照我们理解来实现。


硬件原理图

VBAT供电如图1,2;芯片内部图如图3,4

这里如果是画PCB可以应用如图1,2电路,如果直接用核心板那我们可以接一个3.3v电池,接到VCC-VBAT,然后接一个GND

                                图1

                                        图2

                                                                               图3

                                                                        图4

从手册和图3可知,为了确保RTC在掉电情况下继续运行,可以将低速外部时钟(LSE)接到VBAT引脚上,这样即使系统掉电,RTC可以通过接入的外部时钟继续运行。同时,在系统上电后,可以通过开启低速外部时钟(LES)来确保RTC的正常运行和准确性。这样可以有效保证RTC在掉电情况下的稳定性和准确性,确保系统能够恢复正常工作。


配置寄存器流程如图5

                                                                图5


下面是对rtc进行配置

rtc时钟中断进行初始化

void rtc_init() 
{	//使能备份域时钟 等待可以被操作CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};CKCUClock.Bit.BKP        = 1;CKCU_PeripClockConfig(CKCUClock, ENABLE);if (PWRCU_CheckReadyAccessed() != PWRCU_OK){while (1);}NVIC_EnableIRQ(RTC_IRQn);}


时间

对时间年份,月份进行处理,官方就是严谨。主要有两个函数,第一为判断是否为闰年,第二个函数数计算当前时间。

       

//判断是否是闰年
bool IsLeapYear(u32 year)
{if (((year % 4 == 0) && (year % 100 != 0) ) || (year % 400 == 0) )return TRUE;elsereturn FALSE;
}//调节时间
u8 AP_Time_Adjust(Time_T* AdjustTime)
{u32 i, temp, secsum = 0;temp = AdjustTime->year - 1;for (i = 0; i < (AdjustTime->year - 2014); i++){if (IsLeapYear(temp--) == TRUE){secsum += (366 * 86400);}else{secsum += (365 * 86400);}}temp = 1;for (i = 0; i < (AdjustTime->month - 1); i++){if (temp == 2){if (IsLeapYear(AdjustTime->year) == TRUE)secsum += (29 * 86400);elsesecsum += (28 * 86400);}else{secsum += (Day_Per_Month[temp] * 86400);}temp++;}secsum += ((AdjustTime->day - 1) * 86400);secsum += (AdjustTime->hour * 3600 );secsum += (AdjustTime->minute * 60);secsum += (AdjustTime->second);PWRCU_WriteBackupRegister((PWRCU_BAKREG_Enum) PWRCU_BAKREG_1, secsum);if (PWRCU_ReadBackupRegister((PWRCU_BAKREG_Enum) PWRCU_BAKREG_1) != secsum){return 0;}return 1;
}//计算当前时间
u8 AP_Time_Count(Time_T* CurrentTime)
{u32 i, secsum = 0, temp = 0;secsum = PWRCU_ReadBackupRegister((PWRCU_BAKREG_Enum) PWRCU_BAKREG_1);secsum += RTC_GetCounter();temp = 0;while (secsum >= (365 * 86400)){if (IsLeapYear(2014 + temp)){if (secsum >= (366 * 86400)){temp++;secsum -= (366 * 86400);}else{break;}}else{temp++;secsum -= (365 * 86400);}}CurrentTime->year = 2014 + temp;for (i = 1; i <= 12; i++){if (secsum >= (Day_Per_Month[i] * 86400)){if (i == 2)  // February{if (IsLeapYear(CurrentTime->year)){if (secsum >= (29 * 86400))secsum -= (29 * 86400);elsebreak;}else{secsum -= (28 * 86400);}}else{secsum -= (Day_Per_Month[i] * 86400);}}else{break;}}CurrentTime->month = i;CurrentTime->day = secsum / 86400 + 1;secsum -= ((CurrentTime->day - 1) * 86400);CurrentTime->hour = secsum / 3600;CurrentTime->minute = (secsum % 3600) / 60;CurrentTime->second = (secsum % 3600) % 60;return 1;
}

RTC进行配置

这段代码是一个配置RTC(Real-Time Clock)的函数。函数包括以下步骤:

  1. 调用PWRCU_DeInit()函数,对电源控制单元进行复位操作,确保RTC处于初始状态。

  2. 调用RTC_LSESMConfig()函数配置外部32.768k振荡器为正常模式。

  3. 调用RTC_LSECmd()函数使能LSE(Low Speed External)时钟。

  4. 使用while循环等待LSE稳定就绪,通过CKCU_GetClockReadyStatus()函数判断外部时钟是否准备就绪。

  5. 调用RTC_ClockSourceConfig()函数配置RTC时钟源为LSE。

  6. 调用RTC_IntConfig()函数使能秒中断。

  7. 调用RTC_SetPrescaler()函数设置RTC的分频器分频系数为32768。

  8. 调用RTC_CMPCLRCmd()函数使能比较器清零功能。

void RTC_Configuration(void)
{PWRCU_DeInit();//配置外部32.768k振荡器RTC_LSESMConfig(RTC_LSESM_NORMAL);RTC_LSECmd(ENABLE);while (CKCU_GetClockReadyStatus(CKCU_FLAG_LSERDY) == RESET);RTC_ClockSourceConfig(RTC_SRC_LSE);RTC_IntConfig(RTC_INT_CSEC, ENABLE);RTC_SetPrescaler(RTC_RPRE_32768);RTC_CMPCLRCmd(ENABLE);
}

RTC中断函数

这里设置了一个标志位,当标志位值1是开启RTC中断。

//RTC中断
void RTC_IRQHandler(void)
{u8 bFlags;bFlags = RTC_GetFlagStatus();if (bFlags & 0x1){//1s更新标志位CK_SECOND_Flag = 1;}}

主函数

主函数主要对rtc的应用

#include "ht32.h"
#include "ht32_board.h"
#include "led.h"
#include "delay.h"
#include "USART.h"
#include "IIC.h"
#include "SHT30.h"
//#include "modbus485.h"
#include "motor.h"
#include "DC_Motor.h"
//#include "Timer.h"
#include  "Lock.h"
#include "UART.h"
#include "RTC.h"Time_T DateTime, CurTime;int main()
{char datebuff[40];rtc_init();USART0_Configuration();//读取备份域寄存器 判断RTC是否已经配置if (PWRCU_ReadBackupRegister((PWRCU_BAKREG_Enum) PWRCU_BAKREG_0) != 0xAA55AA55){// RTC 配置RTC_Configuration();	  //设置时间DateTime.year   = 2024;DateTime.month  = 4;DateTime.day    = 29;DateTime.hour   = 18;DateTime.minute = 0;DateTime.second = 0;//使能 RTC RTC_Cmd(ENABLE);PWRCU_WriteBackupRegister((PWRCU_BAKREG_Enum) PWRCU_BAKREG_0, 0xAA55AA55);}while(1){//标志位值1if (CK_SECOND_Flag){CK_SECOND_Flag = 0;//显示当前时间AP_Time_Count(&CurTime);//sprintf函数将当前时间信息(年、月、日、时、分、秒)按指定的格式写入到datebuff字符数组中sprintf(datebuff,"%04d-%02d-%02d %02d:%02d:%02d",CurTime.year,CurTime.month,CurTime.day,CurTime.hour,CurTime.minute,CurTime.second);printf("%s\r\n", datebuff);}}}

演示

直接串口助手演示,3.3V接到VBAT,GND接地,rx-tx,tx-rx。串口助手按照rtc中断每1s打印数据

就算按复位或者烧录,设置T口拔电源,日期计数不变

验证:成功

这篇关于合泰杯(HT32F52352)RTC的应用(计时)--->掉电不丢失VBAT(代码已经实现附带源码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/948532

相关文章

通俗易懂的Java常见限流算法具体实现

《通俗易懂的Java常见限流算法具体实现》:本文主要介绍Java常见限流算法具体实现的相关资料,包括漏桶算法、令牌桶算法、Nginx限流和Redis+Lua限流的实现原理和具体步骤,并比较了它们的... 目录一、漏桶算法1.漏桶算法的思想和原理2.具体实现二、令牌桶算法1.令牌桶算法流程:2.具体实现2.1

MySQL8.0设置redo缓存大小的实现

《MySQL8.0设置redo缓存大小的实现》本文主要在MySQL8.0.30及之后版本中使用innodb_redo_log_capacity参数在线更改redo缓存文件大小,下面就来介绍一下,具有一... mysql 8.0.30及之后版本可以使用innodb_redo_log_capacity参数来更改

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque