天天看点

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

继续阅读