关于RTC秒中断的使用,断电可以继续跑,获取实时时间

RTC其实就是一种计数器,只要纽扣电池存在,RTC就能持续计时,需要给它设置一个初始时间(为了准确需要联网实现,但只使用RTC的话,可以自己创建一个数组来赋初值)

用的是localtime函数,以指针的形式获取到数据的

在主函数中调用设置时间函数(放在循环外,不然每次上电都会重新设置时间,获取一次以后就屏蔽掉,RTC会保存数据的,就可以查看了)

注意:这行代码加上去RTC会一直从0开始,就变成了秒表计数的感觉(千万不能加)

int main(){
	RTC_SetTime();
	__WFI();//闹钟中断的睡眠模式
    while (1)
    {
					
        Sensor_SerialSreen_show();
        rt_thread_delay(50);   //延时50个tick
    }
}

代码如下

rtc.c

#include "rtc.h"
#include "usart.h"
#include "stdio.h"
#include "string.h"
#include "time.h"
#include "public.h"
#include "led.h"
struct tm *d  = NULL;
uint32_t a = 0;
time_t time_cnt;		//定义秒计数器数据类型
//	struct tm time_date;	//定义日期时间数据类型
uint32_t alarm_time;	
void RTC_IRQHandler(void)
{
//	RTC_SetTime();
	//秒中断
	if(RTC_GetITStatus(RTC_IT_SEC)==SET)
	{
		RTC_ClearITPendingBit(RTC_IT_SEC);
		a = RTC_GetCounter();
		d = localtime((time_t *)&a);

    /* Clear Interrupt pending bit */
    RTC_ClearITPendingBit(RTC_FLAG_SEC);

//    printf("%d/%d/%d %02d:%02d:%02d\n", 1900 + p->tm_year, 1+ p->tm_mon, p->tm_mday,p->tm_hour, p->tm_min, p->tm_sec);
			
//			printf("%d/%d/%d  %d/%d/%d  %d\r\n",\
//						d->tm_year+1900,d->tm_mon+1,d->tm_mday,\
//						d->tm_hour,d->tm_min,d->tm_sec,d->tm_wday);
		
	}
	//闹钟中断,修改中,暂时没写完·
	if(RTC_GetITStatus(RTC_IT_ALR)==SET)
	{
		RTC_ClearITPendingBit(RTC_IT_ALR);//清闹钟中断	
		alarm_time=RTC_GetCounter()+1*6;
		alarm_time = alarm_time - alarm_time%60;//设置时精确到分,将秒去除
		RTC_SerAlarmSec(alarm_time);//每来一次闹钟,闹钟时间向后推alarm_time
		LED2(0);
		LED3(0);
//		RTC_ClearITPendingBit(RTC_FLAG_ALR);
		
	}	

}

void RTC_SerAlarmSec(uint32_t s)
{
	//设置时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);	//使能PWR和BKP外设时钟   
	PWR_BackupAccessCmd(ENABLE);	//使能后备寄存器访问  
	RTC_SetAlarm(s);
	RTC_WaitForLastTask();	//等待最近一次对RTC寄存器的写操作完成  
}


void RTC_Config(void)
{
  /* NVIC configuration 中断配置*/
  NVIC_Configuration();

	
	//● 设置寄存器RCC_APB1ENR的PWREN和BKPEN位,使能电源和后备接口时钟
  /* Enable PWR and BKP clocks */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
  //● 设置寄存器PWR_CR的DBP位,使能对后备寄存器和RTC的访问。
  /* Allow access to BKP Domain */
  PWR_BackupAccessCmd(ENABLE);
	
	
	//检测RTC是否已经进行过配置  读取BKP_DR寄存器里面的数据
  if (BKP_ReadBackupRegister(BKP_DR1) != 0xA6A6)
  {
    /* Backup data register value is not correct or not yet programmed (when
       the first time the program is executed) */

//    printf("\r\n\n RTC not yet configured....");

    /* RTC Configuration */
    RTC_Configuration();

    printf("\r\n RTC configured....");


    BKP_WriteBackupRegister(BKP_DR1, 0xA6A6);
  }
  else
  {
    /* Check if the Power On Reset flag is set */
    if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)
    {
//      printf("\r\n\n Power On Reset occurred....");
    }
    /* Check if the Pin Reset flag is set */
    else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)
    {
//      printf("\r\n\n External Reset occurred....");
    }

    printf("\r\n No need to configure RTC....");
    /* Wait for RTC registers synchronization */
    RTC_WaitForSynchro();

    /* Enable the RTC Second */
    RTC_ITConfig(RTC_IT_SEC, ENABLE);
		RTC_ITConfig(RTC_IT_ALR, ENABLE);
    /* Wait until last write operation on RTC registers has finished */
    RTC_WaitForLastTask();
//		get_time();
  }

  /* Clear reset flags */
  RCC_ClearFlag();

//	RTC_SetCounter(0);
//	RTC_SetTime();
	
	/* Wait until last write operation on RTC registers has finished */
	RTC_WaitForLastTask();
	
}


/**
  * @brief  Configures the nested vectored interrupt controller.
  * @param  None
  * @retval None
  */
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure = {0};

  /* Enable the RTC Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

}

/**
  * @brief  Configures the RTC.
  * @param  None
  * @retval None
  */
void RTC_Configuration(void)
{
	


  /* Reset Backup Domain */
  BKP_DeInit();

  /* Enable LSE   打开LSE*/
  RCC_LSEConfig(RCC_LSE_ON);
//	RCC_LSICmd(ENABLE);
	
  /* Wait till LSE is ready   等待LSE准备完毕*/
  while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
  {}

  /* Select LSE as RTC Clock Source  选择RTC时钟源 */
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

  /* Enable RTC Clock  使能RTC时钟 */
  RCC_RTCCLKCmd(ENABLE);

  /* Wait for RTC registers synchronization */
  RTC_WaitForSynchro();
  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();

  /* Enable the RTC Second 开启秒中断*/
  RTC_ITConfig(RTC_IT_SEC, ENABLE);
	RTC_ITConfig(RTC_IT_ALR, ENABLE);	

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();
		
  /* Set RTC prescaler: set RTC period to 1sec 分频*/
  RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();
	
}

uint16_t MyRTC_Time[] = {2023, 11, 14, 17, 16, 00};

void RTC_SetTime(void)
{
	d->tm_year = MyRTC_Time[0] - 1900;		//将数组的时间赋值给日期时间结构体
	d->tm_mon = MyRTC_Time[1] - 1;
	d->tm_mday = MyRTC_Time[2];
	d->tm_hour = MyRTC_Time[3];
	d->tm_min = MyRTC_Time[4];
	d->tm_sec = MyRTC_Time[5];
	
	time_cnt = mktime(d);	//调用mktime函数,将日期时间转换为秒计数器格式
													
	
	RTC_SetCounter(time_cnt);						//将秒计数器写入到RTC的CNT中
	RTC_WaitForLastTask();


}

rtc.h

#ifndef _RTC_H_
#define _RTC_H_

#include "stm32f10x.h"
extern struct tm *d;
//extern	struct tm time_date;	//定义日期时间数据类型

void NVIC_Configuration(void);
void RTC_Configuration(void);
void RTC_Config(void);
void RTC_SetTime(void);
//void RTC_GetTime(void);
//void RTC_SerAlarmSec(uint32_t s);
#endif

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值