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

STM32实时时钟RTC日历算法

[复制链接]
shipeng1989 发布时间: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
支持一个

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似技术帖

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