foggia2004

STM32之RTC配置与初始化-rtc.h rtc.c

<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;
}

 

posted on 2016-01-26 21:00  foggia2004  阅读(1817)  评论(0编辑  收藏  举报

导航