使用STM32的RTC制作万年历

注意:红色代码部分,如果不加这两句,修改时间一直卡死在RTC_WaitForLastTask()




#include "stm32f10x.h"
#include "STM32_RTC.h"

#define  BKP_TIME_FLAG            BKP_DR1
#define  BKP_TIME_YEAR            BKP_DR2
#define  BKP_TIME_MONTH           BKP_DR3
#define  BKP_TIME_DAY             BKP_DR4
#define  BKP_TIME_DATE            BKP_DR5

u32 Month_Days_Accu_C[13] = {0,31,59,90,120,151,181,212,243,273,304,334,365};
u32 Month_Days_Accu_L[13] = {0,31,60,91,121,152,182,213,244,274,305,335,366};
#define SecsPerDay (3600*24)
extern  T_STRUCT  Real_Time;//实时时间值

void RTC_Configuration(void)
{
 
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
 
 PWR_BackupAccessCmd(ENABLE);
 
 BKP_DeInit();
 
 RCC_LSEConfig(RCC_LSE_ON);
 
 while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
 {} 
 
 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
 
 RCC_RTCCLKCmd(ENABLE);
 
 RTC_WaitForSynchro();
 
 RTC_WaitForLastTask();
 
 RTC_ITConfig(RTC_IT_SEC, ENABLE);
 
 RTC_WaitForLastTask();
 
 RTC_SetPrescaler(32767);
 
 RTC_WaitForLastTask();
}

void  RTC_init(void)
{
 
 if(BKP_ReadBackupRegister(BKP_TIME_FLAG) != 0xA5A5)
 {
  
  RTC_Configuration();
  
  Real_Time.year = 2013;
  Real_Time.month = 1;
  Real_Time.day = 1;
  Real_Time.hour = 12;
  Real_Time.minute = 0;
  Real_Time.second = 0;
  Real_Time.date = 1;
  SetRTCTime(&Real_Time);
  BKP_WriteBackupRegister(BKP_TIME_FLAG, 0xA5A5);
 
 }
 else
 {
  if(RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)
  {
    //电源复位
  }
  else if(RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)
  {
    //External Reset occurred
  }
  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
  PWR_BackupAccessCmd(ENABLE);
  BKP_TamperPinCmd(DISABLE);
  BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);
  RTC2Time(); 
  
 }
 RTC_WaitForSynchro();
    RCC_ClearFlag();  //清除RCC重启标志

}


void GetRTCTime(T_STRUCT* time)
{
        RTC_ITConfig(RTC_IT_SEC, DISABLE);        //关闭秒中断
        RTC_WaitForLastTask();

        time->year=Real_Time.year;
        time->month=Real_Time.month;
        time->day=Real_Time.day;
        time->hour=Real_Time.hour;
        time->minute=Real_Time.minute;
        time->second=Real_Time.second;
        time->date=Real_Time.date;

        RTC_WaitForLastTask();
        RTC_ITConfig(RTC_IT_SEC, ENABLE); //打开秒中断
}


const u8 TAB_DATE[12]={6,2,2,5,0,3,5,1,4,6,2,4,};
u8 GetDate(T_STRUCT* time)
{
        return( (time->year + time->year/4 - ( (time->month<3)&&(time->year%4==0) ) + TAB_DATE[time->month-1] + time->day )%7);
}


const u8 Month2Day_Tab[12]={31,28,31,30,31,30,31,31,30,31,30,31} ;

void RTC2Time(void)
{
        u32 count;
        u8 tmp,change=0;

        Real_Time.year=BKP_ReadBackupRegister(BKP_TIME_YEAR);//年值
        Real_Time.month=BKP_ReadBackupRegister(BKP_TIME_MONTH);//月值
        Real_Time.day=BKP_ReadBackupRegister(BKP_TIME_DAY);//日值
        Real_Time.date=BKP_ReadBackupRegister(BKP_TIME_DATE);//星期值

        RTC_ITConfig(RTC_IT_SEC, DISABLE);        //为了避免代码重入引起的问题,这里吧RTC秒中断屏蔽了
        count=RTC_GetCounter();
        //计算新的年月日
        while (count>=0x0001517f)         //上次关电到本次跨越了一天以上
        {
            change=1;
            count-=0x0001517f;
            //星期自加
            if ((++Real_Time.date)>=8)
                    Real_Time.date=1;

            //如果是2月,计算闰年(不需要考虑2099以后的400年一非润)
            if (Real_Time.month==2)
            {
                    if (Real_Time.year%4)
                            tmp=28;
                    else
                            tmp=29;
            }
            else
            {
                    tmp=Month2Day_Tab[Real_Time.month-1];
            }
            if ((++Real_Time.day)>tmp)
            {
                Real_Time.day=1;

                if ((++Real_Time.month)>12)
                {
                    Real_Time.month=1;

                    if ((++Real_Time.year)>=100)
                    {
                            Real_Time.year=0;
                    }
                }
             } 
         //如果跨越了一天,则计算后,要存回寄存器内
         if (change)
         {
             RTC_SetCounter(count);
             BKP_WriteBackupRegister(BKP_TIME_DATE,Real_Time.date);
             BKP_WriteBackupRegister(BKP_TIME_DAY,Real_Time.day);
             BKP_WriteBackupRegister(BKP_TIME_MONTH,Real_Time.month);
             BKP_WriteBackupRegister(BKP_TIME_YEAR,Real_Time.year);
         }
        }
     //计算新的时分秒
        Real_Time.hour=count/3600;
        Real_Time.minute=(count600)/60;
        Real_Time.second=(count600)`;
        //重新打开RTC中断
  // Check if the Power On Reset flag is set
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);  
  
  PWR_BackupAccessCmd(ENABLE);
  
  RTC_WaitForLastTask();
        RTC_ITConfig(RTC_IT_SEC, ENABLE);

}

void SetRTCTime(T_STRUCT* time)
{
        u32 count;
        RTC_ITConfig(RTC_IT_SEC, DISABLE);        //关闭秒中断

        RTC_WaitForLastTask();
        //付时间值到Real_Time上
        Real_Time.year=time->year;
        Real_Time.month=time->month;
        Real_Time.day=time->day;
        Real_Time.hour=time->hour;
        Real_Time.minute=time->minute;
        Real_Time.second=time->second;
        //计算星期
        time->date=Real_Time.date=GetDate(time);

        //把新的年月日存到掉电寄存器上

        BKP_WriteBackupRegister(BKP_TIME_DATE,Real_Time.date);
//        RTC_WaitForLastTask();
        BKP_WriteBackupRegister(BKP_TIME_DAY,Real_Time.day);
//        RTC_WaitForLastTask();
        BKP_WriteBackupRegister(BKP_TIME_MONTH,Real_Time.month);
//        RTC_WaitForLastTask();
        BKP_WriteBackupRegister(BKP_TIME_YEAR,Real_Time.year);
//        RTC_WaitForLastTask();

        //计算新的RTC count值
        count=Real_Time.hour*3600+Real_Time.minute*60+Real_Time.second;
        RTC_WaitForLastTask();
        RTC_SetCounter(count);
       // Check if the Power On Reset flag is set

       //注意红色代码部分,如果不加这两句,修改时间一直卡死在       RTC_WaitForLastTask()
       RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);  
      
       PWR_BackupAccessCmd(ENABLE);
      
        RTC_WaitForLastTask();
        RTC_ITConfig(RTC_IT_SEC, ENABLE); //打开秒中断
}

void RTCTick(void)
{
    u8 tmp;
    if ((++Real_Time.second)>59)
    {
        Real_Time.second=0;
        if ((++Real_Time.minute)>59)
        {
            Real_Time.minute=0;
            if ((++Real_Time.hour)>23)
            {
                Real_Time.hour=0;
                //星期自加
                if ((++Real_Time.date)>=8)
                        Real_Time.date=1;
                //--存储新的星期
                BKP_WriteBackupRegister(BKP_DR5,Real_Time.date);

                //如果是2月,计算闰年(不需要考虑2099以后的400年一非润)
                if (Real_Time.month==2)
                {
                        if (Real_Time.year%4)
                                tmp=28;
                        else
                                tmp=29;
                }
                else
                {
                        tmp=Month2Day_Tab[Real_Time.month-1];
                }
                if ((++Real_Time.day)>tmp)
                {
                    Real_Time.day=1;
                    if ((++Real_Time.month)>12)
                    {
                        Real_Time.month=1;

                        if ((++Real_Time.year)>99)
                        {

                                Real_Time.year=0;
                        }
                        //--储存新的年
                        BKP_WriteBackupRegister(BKP_DR2,Real_Time.year);
                    }
                    //--储存新的月
                    BKP_WriteBackupRegister(BKP_DR3,Real_Time.month);
                }
                //--储存新的日
                BKP_WriteBackupRegister(BKP_DR4,Real_Time.day);
            }
        }
    }
}

 

  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值