中级会员
 
- 积分
- 250
- 金钱
- 250
- 注册时间
- 2019-5-11
- 在线时间
- 39 小时
|
发表于 2020-12-31 11:07:18
|
显示全部楼层
测试已经修复,但是不知道有没有其他问题。
原理:单片机内容计算的世纪秒,我们写和读都是time_t。取得时候需要转换一下。
首先提供一个年月日转time_t的高斯牛逼算法。需要的可以自己替换,测试原子写入时正常的。不需要替换。
/***************************************************************/
//linux struct localtime to time_t
/***************************************************************/
static inline unsigned long mktime (unsigned int year, unsigned int mon,
unsigned int day, unsigned int hour,
unsigned int min, unsigned int sec){
if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
mon += 12; /* Puts Feb last since it has leap day */
year -= 1;
}
return (((
(unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) +year*365 - 719499
)*24 + hour /* now have hours */
)*60 + min /* now have minutes */
)*60 + sec; /* finally seconds */
}
以下是需要替换和修复的地方,我没有在原子的算法上直接修改,而是移植了glic库,但是这个库有个问题月份是0-11,我测试后再最后加上了1.测试了几个年份都是没有问题的
照例先贴。源代码共勉。
#define SECS_PER_HOUR (60 * 60)
#define SECS_PER_DAY (SECS_PER_HOUR * 24)
#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
#define __isleap(year) \
((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
/***************************************************************************//**
* \brief Convert UTC seconds to tm struct.
* \param t : seconds from 1970-1-1 0:0:0
* \param tp : tm struct pointer
* \return 0 : overflow error
* \return 1 : success
* \author glic __offtime
* \note timezone is ignored
* struct tm
* {
* int tm_sec; Seconds. [0-60] (1 leap second)
* int tm_min; Minutes. [0-59]
* int tm_hour; Hours. [0-23]
* int tm_mday; Day. [1-31]
* int tm_mon; Month. [0-11]
* int tm_year; Year - 1900.
* int tm_wday; Day of week. [0-6]
* int tm_yday; Days in year.[0-365]
* }
******************************************************************************/
int gmtime64 (const long long *t, struct tm *tp)
{
const unsigned short int __mon_yday[2][13] =
{
/* Normal years. */
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
/* Leap years. */
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};
long int days, rem, y;
const unsigned short int *ip;
days = *t / SECS_PER_DAY;
rem = *t % SECS_PER_DAY;
while (rem < 0)
{
rem += SECS_PER_DAY;
--days;
}
while (rem >= SECS_PER_DAY)
{
rem -= SECS_PER_DAY;
++days;
}
tp->tm_hour = rem / SECS_PER_HOUR;
rem %= SECS_PER_HOUR;
tp->tm_min = rem / 60;
tp->tm_sec = rem % 60;
/* January 1, 1970 was a Thursday. */
tp->tm_wday = (4 + days) % 7;
if (tp->tm_wday < 0)
tp->tm_wday += 7;
y = 1970;
while (days < 0 || days >= (__isleap (y) ? 366 : 365))
{
/* Guess a corrected year, assuming 365 days per year. */
long int yg = y + days / 365 - (days % 365 < 0);
/* Adjust DAYS and Y to match the guessed year. */
days -= ((yg - y) * 365
+ LEAPS_THRU_END_OF (yg - 1)
- LEAPS_THRU_END_OF (y - 1));
y = yg;
}
tp->tm_year = y - 1900;
if (tp->tm_year != y - 1900)
{
/* The year cannot be represented due to overflow. */
//__set_errno (EOVERFLOW);
return 0;
}
tp->tm_yday = days;
ip = __mon_yday[__isleap(y)];
for (y = 11; days < (long int) ip[y]; --y)
continue;
days -= ip[y];
tp->tm_mon = y;
tp->tm_mday = days + 1;
return 1;
}
/*************************************************************以下是修改代码*****************************************/
//define add
#define SECS_PER_HOUR (60 * 60)
#define SECS_PER_DAY (SECS_PER_HOUR * 24)
#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
#define __isleap(year) \
((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
//add void
int gmtime64 (long long t) //fix to 20201231
{
const unsigned short int __mon_yday[2][13] =
{
/* Normal years. */
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
/* Leap years. */
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};
long int days, rem, y;
const unsigned short int *ip;
days = t / SECS_PER_DAY;
rem = t % SECS_PER_DAY;
while (rem < 0)
{
rem += SECS_PER_DAY;
--days;
}
while (rem >= SECS_PER_DAY)
{
rem -= SECS_PER_DAY;
++days;
}
calendar.hour = rem / SECS_PER_HOUR;
rem %= SECS_PER_HOUR;
calendar.min= rem / 60;
calendar.sec = rem % 60;
/* January 1, 1970 was a Thursday. */
calendar.week = (4 + days) % 7;
if (calendar.week < 0)
calendar.week += 7;
y = 1970;
while (days < 0 || days >= (__isleap (y) ? 366 : 365))
{
/* Guess a corrected year, assuming 365 days per year. */
long int yg = y + days / 365 - (days % 365 < 0);
/* Adjust DAYS and Y to match the guessed year. */
days -= ((yg - y) * 365
+ LEAPS_THRU_END_OF (yg - 1)
- LEAPS_THRU_END_OF (y - 1));
y = yg;
}
calendar.w_year = y;
if (calendar.w_year != y)
{
/* The year cannot be represented due to overflow. */
//__set_errno (EOVERFLOW);
return 0;
}
calendar.w_date= days;
ip = __mon_yday[__isleap(y)];
for (y = 11; days < (long int) ip[y]; --y)
continue;
days -= ip[y];
calendar.w_month = y+1; //20201231 add "+1" fix to month max 11
calendar.w_date = days + 1;
return 1;
}
//原子函数修改
//得到当前的时间
//返回值:0,成功;其他:错误代码.
u8 RTC_Get(void)
{
// static u16 daycnt=0;
long long timecount=0;
// u32 temp=0;
// u16 temp1=0;
// timecount=RTC_GetCounter();
gmtime64(RTC_GetCounter());
// temp=timecount/86400; //得到天数(秒钟数对应的)
// if(daycnt!=temp)//超过一天了
// {
// daycnt=temp;
// temp1=1970; //从1970年开始
// while(temp>=365)
// {
// if(Is_Leap_Year(temp1))//是闰年
// {
// if(temp>=366)temp-=366;//闰年的秒钟数
// else {temp1++;break;}
// }
// else temp-=365; //平年
// temp1++;
// }
// calendar.w_year=temp1;//得到年份
// temp1=0;
// while(temp>=28)//超过了一个月
// {
// if(Is_Leap_Year(calendar.w_year)&&temp1==1)//当年是不是闰年/2月份
// {
// if(temp>=29)temp-=29;//闰年的秒钟数
// else break;
// }
// else
// {
// if(temp>=mon_table[temp1])temp-=mon_table[temp1];//平年
// else break;
// }
// temp1++;
// }
// calendar.w_month=temp1+1; //得到月份
// calendar.w_date=temp+1; //得到日期
// }
// temp=timecount%86400; //得到秒钟数
// calendar.hour=temp/3600; //小时
// calendar.min=(temp%3600)/60; //分钟
// calendar.sec=(temp%3600)%60; //秒钟
// calendar.week=RTC_Get_Week(calendar.w_year,calendar.w_month,calendar.w_date);//获取星期
return 0;
}
/**************************************************************************************************************
修改仓促,如有错误,欢迎斧正!
|
|