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