天天看點

stm32f103 rtc月曆

要做一個基于stm32f103的  rtc月曆,stm32f103 rtc隻有一個32位的計數器,不像現在新出的有專門的日期寄存器可以使用,但是網上早有大牛們寫過這樣的程式,找了個調試,可以用。因為網上有很多,就不再詳細說明,下面是代碼。

/*********時間結構體*******/
typedef struct 
{
	 //公曆年月日周shifenmiao
       u16 w_year;
       u8  w_month;
       u8  w_date;
       u8  week;
	   u8 hour;
       u8 min;
       u8 sec;              
}calendar_tm; 
calendar_tm timer;

/****************************************************************************
* 名    稱:u8 Is_Leap_Year(u16 year)
* 功    能:判斷是否是閏年函數
* 入口參數:u16 year
* 出口參數:u8
* 說    明:該年份是不是閏年.1,是.0,不是
*			月份   1  2  3  4  5  6  7  8  9  10 11 12

*			閏年   31 29 31 30 31 30 31 31 30 31 30 31

*			非閏年 31 28 31 30 31 30 31 31 30 31 30 31
* 調用方法:無 
****************************************************************************/ 
/*u8 Is_Leap_Year(u16 year)
{                     
       if(year%4==0) //必須能被4整除
       { 
              if(year%100==0) 
              { 
                     if(year%400==0)return 1;//如果以00結尾,還要能被400整除          
                     else return 0;   
              }else return 1;   
       }else return 0; 
}  
*/
u8 Is_Leap_Year(u16 year)  //和上面的一樣,都可以使用
{
	return ((year % 4 == 0&& year %100 !=0)||year%400==0);
}                        
/****************************************************************************
* 名    稱:u32 Time_Regulate(void)
* 功    能:調整有格式的時間值
* 入口參數:來自鍵盤輸入
* 出口參數:u32,32位寄存器的值
* 說    明:把鍵盤輸入的時鐘轉換為秒鐘

*			以1970年1月1日為基準

*			1970~2099年為合法年份
* 調用方法:無 
****************************************************************************/  

u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正資料表
const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31}; //平年的月份日期表
u32 Time_Regulate(void)
{
	   u16 syear = 0xFF; u8 smon = 0xFF,sday = 0xFF,hour = 0xFF,min = 0xFF,sec = 0xFF;
       u16 t;
       u32 seccount=0;
  		printf("\r\n==============Time Settings=============================");
  		printf("\r\n  Please Set Year");
 		while(syear == 0xFF)				      
  		{
    		syear = USART_Scanf(4,2099);	         
  		}
 		printf(":  %d", syear); 
		printf("\r\n  Please Set Month");
		while(smon == 0xFF)				      
  		{
    		smon = USART_Scanf(2,12);	         
 		 }
  		printf(":  %d", smon);
		printf("\r\n  Please Set Day");
		while(sday == 0xFF)				      
  		{
    		sday = USART_Scanf(2,31);	         
 		}
  		printf(":  %d", sday);
  		printf("\r\n  Please Set Hours");
  		while(hour == 0xFF)				      
  		{
    		hour = USART_Scanf(2,23);	         
 		 }
  		printf(":  %d", hour); 
  		printf("\r\n  Please Set Minutes");
 		while(min == 0xFF)
  		{
    		min = USART_Scanf(2,59);
  		}
  		printf(":  %d", min); 
  		printf("\r\n  Please Set Seconds");
  		while(sec == 0xFF)
  		{
    		sec = USART_Scanf(2,59);
  		}
  		printf(":  %d", sec); 
       if(syear>=2000&&syear<=2099)  //syear範圍1970-2099,此處設定範圍為2000-2099
	   {        
       	   for(t=1970;t<syear;t++) //把所有 年份的秒鐘相加
       	   {
	              if(Is_Leap_Year(t))seccount+=31622400;//閏年的秒鐘數
	              else seccount+=31536000;                    //平年的秒鐘數
	       }
	       smon-=1;
	       for(t=0;t<smon;t++)         //把前面月份的秒鐘數相加
	       {
	              seccount+=(u32)mon_table[t]*86400;//月份秒鐘數相加
	              if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//閏年2月份增加一天的秒鐘數         
	       }
	       seccount+=(u32)(sday-1)*86400;//把前面日期的秒鐘數相加 
	       seccount+=(u32)hour*3600;//小時秒鐘數
	       seccount+=(u32)min*60;      //分鐘秒鐘數
	       seccount+=sec;//最後的秒鐘加上去
	   }
	   return seccount - 20;	//校正20秒,原因不詳      
}

/****************************************************************************
* 名    稱:void Time_Display(u32 secs)
* 功    能:顯示月曆
* 入口參數:計數器中的值(秒鐘數)
* 出口參數:無
* 說    明:
* 調用方法:無 
****************************************************************************/ 
void Time_Display(u32 secs)
{
    u32 days,temp,years = 1970,months = 0;    
    days = secs/86400;
    if(days > 0)         //超過一天
    {
        temp = days;
        while(temp >= 365)  
        {
            if(Is_Leap_Year(years))              //是閏年
            {
                if(temp >= 366)
                    temp -= 366;    //閏年的天數
                else
                    break;
            }else{
                temp -= 365;
            }          
            years++;
        }
        timer.w_year = years;           //得到年份
    while(days >= 28)
        {
            if(Is_Leap_Year(years) && months ==1)       //判斷是否為閏年的第二月
            {
                if(temp >= 29)
                    temp -= 29;
                else
                    break;
            }else{
                if(temp >= mon_table[months])      
                    temp -= mon_table[months];
                else
                    break;
            }
 
            months++;  
        }
 
        timer.w_month = months+1;             //得到月數
        timer.w_date  = temp+1;               //得到日期
    }
    temp = secs % 86400;                    //得到剩餘秒數
    timer.hour = temp/3600;                 //得到小時
    timer.min = (temp%3600)/60;         
    timer.sec = (temp%3600)%60;
    timer.week = RTC_Get_Week(timer.w_year,timer.w_month,timer.w_date);

       timer.week=RTC_Get_Week(timer.w_year,timer.w_month,timer.w_date);//擷取星期   
       printf("\r\n Time: %0.2d:%0.2d:%0.2d,week:%0.2d,%0.2d:%0.2d:%0.2d",timer.w_year,timer.w_month,timer.w_date,timer.week,timer.hour,timer.min,timer.sec);

}     

/****************************************************************************
* 名    稱:u8 RTC_Get_Week(u16 year,u8 month,u8 day)
* 功    能:輸入公曆日期得到星期(隻允許1901-2099年)		//周日用 “00” 表示
* 入口參數:公曆年月日
* 出口參數:星期  
* 說    明:
* 調用方法:無 
****************************************************************************/                                                                                                                                                    

u8 RTC_Get_Week(u16 year,u8 month,u8 day)
{     
       u16 temp2;
       u8 yearH,yearL;      
       yearH=year/100;    yearL=year%100; 
       // 如果為21世紀,年份數加100  
       if (yearH>19)yearL+=100;
       // 所過閏年數隻算1900年之後的  
       temp2=yearL+yearL/4;
       temp2=temp2%7; 
       temp2=temp2+day+table_week[month-1];
       if (yearL%4==0&&month<3)temp2--;
       return(temp2%7);
}
           

繼續閱讀