合泰杯(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时钟中断进行初始化

cs 复制代码
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);
 
}

时间

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

cs 复制代码
//判断是否是闰年
bool IsLeapYear(u32 year)
{
  if (((year % 4 == 0) && (year % 100 != 0) ) || (year % 400 == 0) )
    return TRUE;
  else
    return 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);
      else
        secsum += (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);
          else
            break;
        }
        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()函数使能比较器清零功能。

cs 复制代码
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中断。

cs 复制代码
//RTC中断
void RTC_IRQHandler(void)
{
  u8 bFlags;

  bFlags = RTC_GetFlagStatus();
  if (bFlags & 0x1)
  {
    //1s更新标志位
    CK_SECOND_Flag = 1;
  }

}

主函数

主函数主要对rtc的应用

cs 复制代码
#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)
	{
                //标志位值1
			if (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口拔电源,日期计数不变

验证:成功

相关推荐
shansz20202 小时前
暂时无法解决的关于STM32F103的RTC日期更新问题
stm32·嵌入式硬件·实时音视频
ZEGO即构开发者2 天前
如何用一句话让AI集成 ZEGO 产品
ai·实时互动·实时音视频·rtc
视频技术分享5 天前
2026年实时音视频服务选型深度解析
音视频·实时音视频·视频
摸摸电5 天前
RTC电路电池寿命计算?
实时音视频
深圳市友昊天创科技有限公司8 天前
友昊天创推出8K ,4K 120Hz 100米延长器方案
音视频·实时音视频·视频编解码
视频技术分享8 天前
国产化视频会议安全加密技术行业应用案例集
音视频·实时音视频
深圳市友昊天创科技有限公司9 天前
ASM4242 雷电扩展坞 CV4242 PCIE扩展坞
音视频·实时音视频·视频编解码
CjWjPexPQY9 天前
引入模糊神经网络对123等级负荷进行功率分配的风光MPPT+VCS逆变并网simiulink/...
实时音视频
深圳市友昊天创科技有限公司9 天前
友昊天创推出延长器方案GSV5600+HDBase VS010**/VS100**
音视频·实时音视频·视频编解码
TEL1892462247712 天前
IT6227:USB-C(DP Alt 模式)及电源传输控制器 内置 4 通道 DP 1.4 转 HDMI 2.1 转换器
音视频·实时音视频·视频编解码