芯片内集成了计数器+存储器 外面接电源+晶振即可代码表现为一个init+一个算法
#include "rtc.h"
void STEP1_RCC(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
}
void STEP2_NVIC(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void Set_alarm(uint32_t AlarmValue)
{
if(RTC_GetITStatus(RTC_IT_ALR) != RESET) //alarm interrupt
{
RTC_ClearITPendingBit(RTC_IT_ALR);
}
RTC_ITConfig(RTC_IT_ALR, ENABLE);
RTC_WaitForLastTask();
RTC_SetAlarm(AlarmValue);
}
void Disable_alarm(void)
{
RTC_ITConfig(RTC_IT_ALR , DISABLE);
RTC_WaitForLastTask();
}
void RTC_Configuration(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);
//允许访问BKP区域
PWR_BackupAccessCmd(ENABLE);
//复位BKP
BKP_DeInit();
//使能外部低速晶振 32.768K
RCC_LSEConfig(RCC_LSE_ON);
//等待外部低速晶振就绪
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET);
//选择RTC外部时钟为低速晶振 32.768K
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
//使能RTC时钟
RCC_RTCCLKCmd(ENABLE);
//等待RTC寄存器同步
RTC_WaitForSynchro();
//等待写RTC寄存器完成
RTC_WaitForLastTask();
//使能RTC秒中断
RTC_ITConfig(RTC_IT_SEC,ENABLE);
Set_alarm(2);
//设置预分频
RTC_SetPrescaler(32767);
//等待写RTC寄存器完成
RTC_WaitForLastTask();
}
void Clock_Init(void)
{
if(BKP_ReadBackupRegister(BKP_DR1)!=0xA5A5)
{
//第一次运行 初始化设置
//RTC初始化
RTC_Configuration();
//等待写RTC寄存器完成
RTC_WaitForLastTask();
//设置时间初值
RTC_SetCounter(0xA442);
//等待写RTC寄存器完成
RTC_WaitForLastTask();
//写配置标志
BKP_WriteBackupRegister(BKP_DR1,0xA5A5);
}
else
{
//等待RTC寄存器同步
RTC_WaitForSynchro();
//等待写RTC寄存器完成
RTC_WaitForLastTask();
//使能RTC秒中断
RTC_ITConfig(RTC_IT_SEC,ENABLE);
//等待写RTC寄存器完成
RTC_WaitForLastTask();
Set_alarm(2);
}
RCC_ClearFlag();//清除复位标志;
}
void RTC_Init(void)
{
STEP1_RCC();
STEP2_NVIC();
Clock_Init();
}
/***********************判断是否为闰年********/
const uint8_t monthTable[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
/*
函数功能:判断是否闰年
函数参数:需要判断的年份
返回值: 返回1成功 其他失败
*/
static uint8_t isLeapYear(uint16_t mYear)
{
if (((mYear%4 == 0)&&((mYear%100) != 0))||(mYear%400) == 0)
{
return 1;
}else
{
return 0;
}
}
/********************************************************************************/
/*
函数功能:日期转换为秒并配置RTC
函数参数:年、月、日、时、分、秒
返回值: 返回0成功 其他失败
*/
uint8_t RTC_SetSec(_TM* DATA)
{
uint32_t secCount = 0;
uint16_t i;
uint16_t year=DATA->year;
uint8_t month=DATA->mon;
uint8_t day=DATA->day;
uint8_t hour=DATA->hour;
uint8_t minute=DATA->min;
uint8_t sec=DATA->sec;
if (year <1970 || year >2099)
{
return 1;
}
for (i=1970; i<year; i++)
{
if (isLeapYear(i))
{
secCount += 31622400UL;
}
else
{
secCount += 31536000UL;
}
}
for (i=0; i<month-1; i++)
{
secCount += ((uint32_t)monthTable[i]*86400UL);
if (isLeapYear(year) && i==1) //润年 多加一天
{
secCount += 86400UL;
}
}
secCount += (uint32_t)(day-1) * 86400UL;
secCount += (uint32_t)(hour)*3600;
secCount += (uint32_t)(minute)*60;
secCount += (uint32_t)(sec);
/*执行以下操作可以使能对备份寄存器和 RTC 的访问:
1)通过设置寄存器 RCC_APB1ENR 的 PWREN 和 BKPEN 位来打开电源和后备接口的时钟
2)电源控制寄存器(PWR_CR)的 DBP 位来使能对后备寄存器和 RTC 的访问
*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
RTC_SetCounter(secCount);
RTC_WaitForLastTask();
return 0;
}
/********************************************************************************/
/*
函数功能:从RTC获取秒转换为年、月、日、星期、时、分、秒
存入 struct thisDate 中
函数参数:struct thisDate
返回值: 返回0成功 其他失败
*/
uint8_t RTC_GetDate(_TM* thisDate)
{
uint32_t timeCount = 0;
uint32_t Count ;
uint16_t tmp = 0;
timeCount = RTC_GetCounter();
Count = timeCount/86400UL; //计算出天数
thisDate->week = (4+Count)%7;
if (Count !=0) //大于一天
{
tmp = 1970; //从1970年开始
while(Count>=365)
{
if (isLeapYear(tmp))//是闰年
{
if (Count>= 366) //天数大于366
{
Count -= 366;
}else
{
tmp++; //天数小于366 最后一年
break;
}
}else
{
Count -= 365; //平年
}
tmp++;
}
thisDate->year = tmp; //获取到了年
tmp = 0;
while(Count>= 28)
{
if (isLeapYear(thisDate->year) && tmp == 1)
{
if (Count >= 29)
{
Count -= 29;
}
else
{
break; //当年是闰年 二月 某时
}
}else
{
if (Count >= monthTable[tmp])
{
Count -= monthTable[tmp];
}else
{
break;
}
}
tmp ++;
}
thisDate->mon = tmp+1; //获取到月
thisDate->day = Count+1; //获取到日
}
Count = timeCount%86400UL;
thisDate->hour = Count/3600;
thisDate->min= (Count%3600)/60;
thisDate->sec = (Count%3600)%60;
return 0;
}
_RTC Rtc = {RTC_Init,RTC_GetDate,RTC_SetSec};
_TM Today={12,27,13,1,8,8,2018};
#ifndef __RTC_H
#define __RTC_H
#include "time.h"//等待研究
#include "stm32f10x_bkp.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_rtc.h"
#include "stm32f10x_pwr.h"
#include "misc.h"
typedef struct
{
u8 sec;
u8 min;
u8 hour;
u8 week;
u8 day;
u8 mon;
u16 year;
}_TM;
typedef struct
{
void (*init)(void);
u8 (*GetTime)(_TM *);
u8 (*SetTime)(_TM *);
}_RTC;
extern _RTC Rtc;
extern _TM Today;
#endif
|