⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 opexdatetime.c

📁 学完单片机就要使用实时系统在单片机上运行
💻 C
字号:
////////////////////////////////////////////////
// OPEXdateTime.c
// (C) 2004 Steve Childress stevech@san.rr.com
////////////////////////////////////////////////

#include "OPEX.h"



const unsigned char __attribute__((progmem)) MONTHNAMES[] = {
		"JanFebMarAprMayJunJulAugSepOctNovDec" };
const unsigned char __attribute__((progmem)) DAYNAMES[] = {
		"SunMonTueWedThuFriSat" };

int IsLeapYear(int);

int8_t GMT_offset;	// GMT offset hours signed

///////////////////////////////////////////

void OPEX_init_dateTime(void)
{
	if (time.year == 0)  {
		OPEX_date_stuff(&time, 0, 1, 1, 0, 0, 0, 0);	// jan 1 of 2000
	}
}

//////////////////////////////////////////////
// return a formatted string for the date passed
void OPEX_format_date(char *p, DATE_TIME *buf)
{
	char mmm[4];
	char ddd[4];
	
	buf->weekday = OPEX_DayOfWeek((int)buf->year, (int)buf->month, (int)buf->day);
	memcpy_P(&mmm, &MONTHNAMES[(buf->month-1) * 3], 3);	// three letter monthname
	memcpy_P(&ddd, &DAYNAMES[buf->weekday * 3], 3);	// three letter dayname
	mmm[3] = 0;
	ddd[3] = 0;
	sprintf_P(p, PSTR(" %s %02d %s %02d "), ddd, (int)buf->day, mmm, (int)buf->year);
}


///////////////////////////////////////////////////////////
// return a formatted string for the time passed
void OPEX_format_time(char *p,  DATE_TIME *buf)
{
	int frac;

	frac =  (int)buf->tick;
	frac *= 10;  // mul by 100 yields linker error __mulhi3
	frac = (frac * 10) / TicksPerSecond;
	
	*p = '\0';
	sprintf_P(p,  PSTR( " %02d:%02d:%02d.%02d "), buf->hour, buf->minute, buf->second, frac);
}

///////////////////////////////////////////////////////////
// return a formatted string for the date and time passed
void OPEX_format_date_time(char *p,  DATE_TIME *buf)
{
	char ddd[16];	// large enough to hold:  mmm dd, yyyy\0	
	
	OPEX_format_time(p, buf);		// put time into passed string buf
	OPEX_format_date(ddd, buf);		// put date into local string
	strcat(p, ddd);				// join strings
}



///////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////

extern const unsigned char __attribute__((progmem)) MAX_DAY[];
extern const unsigned char __attribute__((progmem)) MAX_DAYLEAP[];



///////////////////////////////////////////////
// get a copy of the current time of day
void OPEX_now(DATE_TIME *buf)
{	
	cli();
	memcpy(buf, &time, sizeof(time));
	sei(); 
}

///////////////////////////////////////////////
// store date time in the structure passed
void OPEX_date_stuff(DATE_TIME *t, BYTE year, BYTE month, BYTE day, BYTE hour, BYTE minute, BYTE second, BYTE tick)
{
	cli();  // don't let ISR alter if this is the system time being altered
	t->year = year;
	t->month = month;
	t->day = day;
	t->hour = hour;
	t->minute = minute;
	t->second = second;
	t->tick = tick;	
	t->weekday = OPEX_DayOfWeek((int)t->year+2000, (int)t->month, (int)t->day);
	sei();
}


///////////////////////////////////////////////
// compute new date and time given a delta 
void OPEX_date_add(DATE_TIME *t, BYTE days, BYTE hours, BYTE minutes, BYTE seconds, BYTE ticks)
{
	int n;
	
	// add ticks
	n = (int) t->tick + (int) ticks;	// add ticks
	if (n >= (int) TicksPerSecond)  {  // assumed to be byte-sized
		t->tick = 0;
		++t->second;
	}
	else
		t->tick = (BYTE) n;  // is modulo, from the above
	
	// add seconds, minutes, hours, days
	t->second += seconds;	
	if (t->second >= 60)  {
		t->second = 0;
		++t->minute;
	}
	t->minute += minutes;
	if (t->minute >= 60)  {
		t->minute = 0;
		++t->hour;
	}
	t->hour += hours;
	if (t->hour >= 24)  {
		t->hour = 0;
		++t->day;
	}
	t->day += days;
	
	// add months, years
	if (!IsLeapYear(t->year + 2000))  {
	//if((t->year & 3) != 0)  {  // leap year ignore 2099?
		if((int)t->day > (int)PRG_RDB(&MAX_DAY[t->month]))  {	 // 1..12
			t->day = 1;	// enough days for this month?
			if(++t->month > 12)	{
				t->month = 1;	// another year gone by..
				++t->year;
			}
		}
	}
	else  {
		if((int)t->day > (int)PRG_RDB(&MAX_DAYLEAP[t->month]))	{   // 1..12
			t->day = 1;	// enough days for this month?
			if(++t->month > 12)	{
				t->month = 1;	// another year gone by..
				++t->year;
			}
		}
	}
	t->weekday = OPEX_DayOfWeek((int)t->year+2000, (int)t->month, (int)t->day);
}


// /////////////////////////////////////////////////
// Compare two date/time structures
// return -1 if t1 < t2
// return  0 if t1 == t2
// return  1 if t1 > t2er

int OPEX_compare_dt(DATE_TIME *t1,  DATE_TIME *t2)
{
	unsigned char *p1, *p2, i;
	int ret;
	
	p1 = (unsigned char *)t1;
	p2 = (unsigned char *)t2;
	

	// compare two date blocks
	// don't need to block interrupts, since time values changes in the ISR are monotonic/ascending?
	ret = 0; //assume equality
	cli();	// one may be volatile real time date
	for (i = 0; i < sizeof(DATE_TIME); i++)  { // bytes are in decending order yr/mo/day/hour/min/sec/frac
		if (*p1 < *p2)  {
			ret = -1;
			break;
		}
		if (*p1 > *p2)  {
			ret = 1;
			break;
		}
		++p1;
		++p2;
	}
	sei();
	return(ret);		
}

///////////////////////////////////////////////////////////////////////////
// THE CODE BELOW, MODIFIED FROM THE BELOW SOURCE:
/*
    begin                : Sunday  July 7 11:13:38 GMT+8 2002
    copyright            : (C) 2002 by Jerry Jenkins
    email                : Jerry_J_Jenkins@hotmail.com
 ***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
*/


/////////////////////////////////////////////////////////////
int	IsLeapYear( int nYear )
{
	if( nYear % 4 != 0 )	return 0;
	if( nYear % 100 != 0 )	return 1;
	return ( nYear % 400 == 0 );
}
/////////////////////////////////////////////////////////////
/*
 *	Count of days, which is Feb 29, from Jan 1, 0 to Jan 1, nYear
 *	There is no Feb 29 between Jan 1, 0 and Jan 1, -3, one between Jan 1, 0 and Jan 1, -4
 *	one between Jan 1, 0 and Jan 1, 3 AD, one between Jan 1, 0 and Jan 1, 4
 */
int	CountOfFeb29( int nYear )
{
	int		nCount = 0;

	if( nYear > 0 ) {
		nCount = 1;	/* Year 0 is a leap year */
		nYear--;/* Year nYear is not in the period */
	}
	nCount += nYear / 4 - nYear / 100 + nYear / 400;

	return nCount;
}


static int	pnDaysBeforeMonth[] = {
		 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
	};
////////////////////////////////////////////////////////////
// returns day of week, 0 = Sunday
int	OPEX_DayOfWeek( int nYear, int nMonth, int nDay )
{
	int			nDayOfWeek;
	

#if 0 // don't error check	to save code space
	if ( nDay < 0 || nMonth < 0 || nMonth > 12 )
		return(-1);
	
	if ( 
		( nDay <= ( pnDaysBeforeMonth[ nMonth+1 ] - pnDaysBeforeMonth[ nMonth ] ) )
		|| ( nMonth == 2 && nDay == 29 && IsLeapYear(nYear) ) )
		return(-1);
#endif
	
	/* the day of Jan 1, nYear */
	nDayOfWeek = 6 + nYear % 7 + CountOfFeb29(nYear) % 7 + 14; /* + 14 : makes nDayOfWeek >= 0 */
	
	/* the day of nMonth 1, nYear */
	nDayOfWeek += pnDaysBeforeMonth[ nMonth ];
	if( nMonth > 2 && IsLeapYear(nYear) )	nDayOfWeek++;
	
	/* the day of nMonth nDay, nYear */
	nDayOfWeek += nDay - 1;
	nDayOfWeek %= 7;
	
	return nDayOfWeek;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -