1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > rtc校准算法_STM32实时时钟RTC日历算法

rtc校准算法_STM32实时时钟RTC日历算法

时间:2021-06-28 12:35:56

相关推荐

rtc校准算法_STM32实时时钟RTC日历算法

本帖最后由 shipeng1989 于 -5-16 08:32 编辑

最近工作上需要利用STM32的自带RTC编写日历功能。其实对于公历万年历并不是很复杂,但是由于自带RTC断电后只能做32位二进制秒计数不能更新日期信息,要从根本上解决这个问题就需要编写一个算法可以根据计数器RTC_CNT的当前值计算出当前日期。由于32位的RTC_CNT的最大计数值0xFFFFFFFF/秒,即135年左右,因此这个算法只适用于2000年~2099年。由于日历的时间跨度大短时间内很难通过测试发现bug,所以恳请大家帮忙排查一下是否存在bug并跟帖回复

编写思路是这样的:在100年范围内刚好是4年1闰,也就是每4年1个周期=366+365*3天,当前总天数days=RTC_CNT/(24*3600),年year=days/(366+365*3)*4 + days%(366+365*3)/365,月和日的算法请直接参照下列代码:

const u8 yizhou[]={"六日一二三四五"};//从六开始是因为日期的起点是2000年1月1日这一天是星期六

struct RtcReg

{

u32 days;

u8 date;

u8 month;

u8 year;

};

void TranslateYMD(struct RtcReg *RtcRegs)//在调用此函数前,RtcRegs->days需赋值当前天数值RTC_CNT/(24*3600)

{

u8 i,j;u16 u16buf=RtcRegs->days;

RtcRegs->year = u16buf/(366+365*3)*4;

u16buf %= (366+365*3);//4年为一个周期,当前周期内的天数

RtcRegs->year += u16buf/365;//加上当前4年周期内的年

if (u16buf==365)RtcRegs->year--;//4年周期中的第一年为闰年366天,如果天数u16buf等于365则上一句多算了1年//年计算完成,开始月和日计算:

else if (u16buf>365)u16buf = (u16buf-1)%365;//得到当前年中的天数,如u16buf超过365则经过了1个闰年u16buf减1再对365求余

i = (RtcRegs->year&3)?0:1;//当前年份为 平年i=0/闰年i=1

RtcRegs->month = u16buf/(181+i);//1年分为两个181+i天,即以7月1日为界限,分别计算月份

RtcRegs->month = RtcRegs->month*6;

if (RtcRegs->month<12)RtcRegs->month++;

if (RtcRegs->month<7)

{

// 大于59+i即经过了2月份需补3-i天 大于120+i即经过了4月份需补1天

j = u16buf + ((u16buf<59+i)?0: (3-i))+((u16buf

RtcRegs->month += j/31;RtcRegs->date = j%31+1;

}

else if (RtcRegs->month==7)

{

u16buf -= 181+i;

// 大于92即经过了9月需补1天 大于153即经过了11月需补1天

j = u16buf + ((u16buf<92)?0:1)+((u16buf<153)?0:1);

RtcRegs->month += j/31;RtcRegs->date = j%31+1;

}

//12月份减去1-11月的天数(334+i)由于日是从1开始没有0因此需要加1即-(334+i)+1=-(333+i)

else RtcRegs->date = u16buf - (333+i);

}

void DisplayYMDW(struct RtcReg *RtcRegs)//日期显示子程序

{

Disp1Char(2,3,yizhou[RtcRegs->days%7*2]);//星期

LCD_Wdata(yizhou[RtcRegs->days%7*2+1]);//星期,由于一个汉字占用2个字节,因此星期需发送两个字节

LCD_Wdata('2');

LCD_Wdata('0');

LCD_Wdata((RtcRegs->year/10)+'0');

LCD_Wdata((RtcRegs->year%10)+'0');

LCD_Wdata('-');

LCD_Wdata((RtcRegs->month/10)+'0');

LCD_Wdata((RtcRegs->month%10)+'0');

LCD_Wdata('-');

LCD_Wdata((RtcRegs->date/10)+'0');

LCD_Wdata((RtcRegs->date%10)+'0');

}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。