|
本帖最后由 shipeng1989 于 2019-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<i+120)?0:1); 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'); } |
微信公众号
手机版
这个是我写的 RTC 时间处理,直接丢给 newlib 标准库(我用的是 GCC 开发环境,标准库是 newlib)的时间函数了。http://github.com/SushiBits/LCDC ... stem/src/time.c#L96
RTC 接入 newlib 标准库时间函数:http://github.com/SushiBits/LCDC ... stem/src/time.c#L96
用标准库时间函数显示当前时间:http://github.com/SushiBits/LCDC ... 1a7e/src/main.c#L87