你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32实时时钟RTC日历算法

[复制链接]
歹徒兄弟 发布时间:2017-12-3 18:59
本帖最后由 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');
}
收藏 1 评论4 发布时间:2017-12-3 18:59

举报

4个回答
maxtch 回答时间:2017-12-3 19:21:19
你用的是什么开发工具?其实你可以直接拿 C 标准库里面的时间函数,这个 32 位计数器正好匹配标准库里面的 time_t。

这个是我写的 RTC 时间处理,直接丢给 newlib 标准库(我用的是 GCC 开发环境,标准库是 newlib)的时间函数了。http://github.com/SushiBits/LCDC ... stem/src/time.c#L96
maxtch 回答时间:2017-12-3 19:24:04
其实标准库里面很有可能已经有时间函数了,把 RTC 接进去就可以。下面有一个我写的程序,用的标准库时间函数。

RTC 接入 newlib 标准库时间函数:http://github.com/SushiBits/LCDC ... stem/src/time.c#L96
用标准库时间函数显示当前时间:http://github.com/SushiBits/LCDC ... 1a7e/src/main.c#L87
anywill 回答时间:2017-12-3 21:23:50
学习了
MrJiu 回答时间:2017-12-4 09:10:17
支持一个

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版