<rtc.h>
#include "stm32f10x.h"
#ifndef _RTC_H
#define _RTC_H
typedef struct
{
vu8 hour;
vu8 mintue;
vu8 second;
vu16 year;
vu8 month;
vu8 day;
vu8 week;
}_calendar_obj;
// extern _calendar_obj Calendar;
u8 RTC_Init(void);
u8 Is_Leap_Year(u16 _year);
_calendar_obj RTC_GetCalendar(void);
u8 RTC_GetWeek(u16 _year,u8 _month,u8 _day);
u8 RTC_SetCalendar(u16 _year,u8 _month,u8 _day,u8 _hour,u8 _min,u8 _second);
#endif
<rtc.c>
#include "rtc.h"
const u8 month_table[]={31,28,31,30,31,30,31,31,30,31,30,31};
const u8 week_table[]={0,3,3,6,1,4,6,2,5,0,3,5};
_calendar_obj Calendar;
void delay_ms(u16 time)
{
u16 i=0;
while(time--)
{
i=12000;
while(i--);
}
}
u8 Is_Leap_Year(u16 _year)
{
if((_year%4 && _year%100!=0) | (_year%400==0)) return 0;
else return 1;
}
u8 RTC_Init(void)
{
u16 temp=0;
//enable RTC_CLK outside
if(BKP_ReadBackupRegister(BKP_DR1)!=0x5050)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE);
PWR_BackupAccessCmd(ENABLE);
BKP_DeInit();
RCC_LSEConfig(RCC_LSE_ON);
while(RCC_GetFlagStatus(RCC_FLAG_HSERDY)==RESET)
{
temp++;
delay_ms(10);
}
if(temp>250) return 0;
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForLastTask();
RTC_ITConfig(RTC_IT_SEC,ENABLE);
RTC_WaitForLastTask();
RTC_SetPrescaler(32767);
RTC_WaitForLastTask();
RTC_SetCalendar(2015,10,10,10,10,10);
RTC_ExitConfigMode();
BKP_WriteBackupRegister(BKP_DR1,0x5050);
}
else
{
RTC_WaitForSynchro();
RTC_ITConfig(RTC_IT_SEC,ENABLE);
RTC_WaitForLastTask();
}
return 1;
}
_calendar_obj RTC_GetCalendar(void)
{
static u16 daycount=0;
u32 timecount=RTC_GetCounter();
u32 daynum=timecount/86400; //day
u16 temp=0;
//Calendar year
if(daycount!=daynum) //>1
{
daycount=daynum;
temp=1970;
while(daynum>365)
{
if(Is_Leap_Year(temp))
{
if(daynum>=366)
daynum=daynum-366;
else
break;
}
else
daynum=daynum-365;
temp++;
}
Calendar.year=temp; // set year
temp=0; //reset temp
// Calendar month
while(daynum>=28)
{
if(Is_Leap_Year(Calendar.year) && temp==1)
{
if(daynum>=29) daynum=daynum-29;
else break;
}
else
{
if(daynum>=month_table[temp])
daynum=daynum-month_table[temp];
else
break;
}
temp++;
}
Calendar.month=temp+1; //set month
Calendar.day=daynum+1; //set day
}
daynum=timecount%86400;
Calendar.hour=daynum/3600; //set hour
Calendar.mintue=(daynum%3600)/60; //set mintue
Calendar.second=(daynum%3600)%60; //set second
return Calendar;
}
u8 RTC_SetCalendar(u16 _year,u8 _month,u8 _day,u8 _hour,u8 _min,u8 _second)
{
u16 i;
u32 seccount=0; //second total
if(_year<1970 || _year>2099) return 1; //valid year
//calculate year
for(i=1970;i<_year;i++)
{
if(Is_Leap_Year(i))
seccount=seccount+3600*24*366; //3600*24*366=31622400
else
seccount=seccount+3600*24*365; //3600*24*365=31536000
}
//calculate month
_month=_month-1;
for(i=0;i<_month;i++)
{
seccount=seccount+(u32)month_table[i]*3600*24;
if(Is_Leap_Year(_year) && i==1) //February,add 1 day
{
seccount=seccount+3600*24;
}
}
//calculate day
seccount=seccount+(u32)(_day-1)*3600*24;
seccount+=(u32)_hour*3600;
seccount+=(u32)_min*60;
seccount+=_second;
//set Calendar
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE);
PWR_BackupAccessCmd(ENABLE);
RTC_SetCounter(seccount);
RTC_WaitForLastTask();
return 0;
}
u8 RTC_GetWeek(u16 _year,u8 _month,u8 _day)
{
u16 temp;
u8 yearH,yearL;
yearH=_year/100; // 2016/100=20
yearL=_year%100; // 2016%100=16
if(yearH>19) yearL+=100;
temp=yearL+yearL/4;
temp=temp+_day+week_table[_month-1];
if(yearL%4==0 && _month<3)
temp=temp-1;
return temp%7;
}