软件RTC在单片机上的C语言实现(二)
一.前言
上一篇文章讲了软件rtc实现的第一种方法,用的是相对天数值,然后通过两个转换函数作为单片机内部系统与现实日期的接口。废话不多说,今天贴第二种实现方法,也是最传统的软件rtc处理方法。
二.实现
2.1 定义结构体类型和变量
typedef struct
{
u32 minute :6;
u32 hour :5;
u32 date :5;
u32 month :4;
u32 year :8;
u32 weekDay :4;
}ST_RTCDATA;
//rtc值
ST_RTCDATA gs_RtcData;
//列举闰年时候每个月的天数
u8 gs_LeapYearMonDays[12]={31,29,31,30,\
31,30,31,31,\
30,31,30,31};
//列举平年的时候每个月的天数
u8 gs_OrdYearMonDays[12]={31,28,31,30,\
31,30,31,31,\
30,31,30,31};
//秒值
u8 gu8_CurSecond;
//rtc是否完成了初始化,当获取到了外部时间且赋值到了gs_RtcData将其更新为1
u8 gu8_RtcInitFlg;
肯定有人会想为什么我定义的这个ST_RTCDATA结构体不包含秒值,为什么要用C语音中的位字段的写法。其实这样写是为了方便rtc值大小的比较。我会在文章后面讲述关于带有时间属性的数据做排序和比较的时候详细介绍。
2.2 软件rtc的时间更迭的实现
//传入当前实际年份减去2000后的值
//闰年返回1,平年返回0
u8 Rtc_IsLeapYear(u8 curYear)
{
if(curYear%4==0)
{
return 1;
}
else
{
return 0;
}
}
//软件rtc,1s调用一次
void Rtc_Loop(ST_RTCDATA *time)
{
u8 monthDays=0;
//时间经过校准后再运行软件rtc
if(!gu8_RtcInitFlg)
{
return;
}
gu8_CurSecond++;
if(gu8_CurSecond>=60)
{
gu8_CurSecond=0;
time->minute++;
if(time->minute>=60)
{
time->minute=0;
time->hour++;
if(time->hour>=24)
{
time->hour=0;
time->date++;
time->weekDay++;
//更新星期值
if(time->weekDay>7)
{
time->weekDay=1;
}
//获取当前年份月份的天数
if(Rtc_IsLeapYear(time->year)) //闰年
{
monthDays=gs_LeapYearMonDays[time->month-1];
}
else //平年
{
monthDays=gs_OrdYearMonDays[time->month-1];
}
//如果当前日期大于当前月份的天数了,月份加1,天数置为1
if(time->date>monthDays)
{
time->date=1;
time->month++;