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