要做一個基于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);
}