单片机RTC应用函数_单片机格林时间

RTC时钟几乎是现在单片机的标配,特别在做物联网相关的项目的时候,这个功能几乎是必需品,现总结几个常用的函数;

1、RTC与BDC码的转换

/********************************************************************
*@函数名:bsp_BCD_Check
*@功  能:检查BCD码格式
*@形  参:bcd 需要检验的 BCD 码
*@返回值:-1 不合格   0 属于BCD码
*@备  注:NULL
********************************************************************/
int bsp_BCD_Check(uint8_t bcd)
{
	uint8_t byte;
	byte = bcd&0X0F;
  if(byte > 9) return -1;
	byte = (bcd>>4)&0X0F;
	if(byte > 9) return -1;
	
	return 0;
}



/********************************************************************
*@函数名:bsp_BCDToHex
*@功  能:将BCD转换成HEX码
*@形  参:bcd 需要转换的 BCD 码
*@返回值:转换后的十六进制码
*@备  注:NULL
********************************************************************/
uint8_t bsp_BCDToHex(uint8_t bcd)
{
  uint8_t byte;
	byte = (bcd>>4)*10+(bcd&0X0F);
	return byte;
}


/********************************************************************
*@函数名:bsp_BCDToHex
*@功  能:将HEX换成BCD码
*@形  参:hex 需要转换的 HEX 码
*@返回值:转换后的BCD码
*@备  注:NULL
********************************************************************/
uint8_t bsp_HexToBCD(uint8_t hex)
{
  uint8_t byte;
	byte = (hex/10)%10;
	byte = (byte<<4)+hex%10;
	return byte;
}


2、RTC时间戳的转换

/* 定义时间结构体 */
struct rtc_time {
	int tm_year;
	int tm_mon;
	int tm_mday;
	int tm_hour;
	int tm_min;
	int tm_sec;
	int tm_wday;
};


/* 定义相关的宏 */
#define FEBRUARY		      2
#define	STARTOFTIME		    1970
#define SECDAY			      86400L           /*  一天有多少s */
#define SECYR			        (SECDAY * 365)
#define	leapyear(year)		((year) % 4 == 0)
#define	days_in_year(a) 	(leapyear(a) ? 366 : 365)
#define	days_in_month(a) 	(month_days[(a) - 1])



static int month_days[12] = {	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

/*
 * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
 */
/*计算公历*/
void GregorianDay(struct rtc_time * tm)
{
	int leapsToDate;
	int lastYear;
	int day;
	int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };

	lastYear = tm->tm_year-1;

	/*计算从公元元年到计数的前一年之中一共经历了多少个闰年*/
	leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;      

     /*如若计数的这一年为闰年,且计数的月份在2月之后,则日数加1,否则不加1*/
	if((tm->tm_year%4==0) &&
	   ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) &&
	   (tm->tm_mon>2)) {
		/*
		 * We are past Feb. 29 in a leap year
		 */
		day=1;
	} else {
		day=0;
	}

	day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday; /*计算从公元元年元旦到计数日期一共有多少天*/

	tm->tm_wday = day%7;
	if(tm->tm_wday == 0)
	{
	  tm->tm_wday = 7;
	}
}

/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
 * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
 * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
 *
 * [For the Julian calendar (which was used in Russia before 1917,
 * Britain & colonies before 1752, anywhere else before 1582,
 * and is still in use by some communities) leave out the
 * -year/100+year/400 terms, and add 10.]
 *
 * This algorithm was first published by Gauss (I think).
 *
 * WARNING: this function will overflow on 2106-02-07 06:28:16 on
 * machines were long is 32-bit! (However, as time_t is signed, we
 * will already get problems at other places on 2038-01-19 03:14:08)
 *
 */
uint32_t mktimev(struct rtc_time *tm)
{
	if (0 >= (int) (tm->tm_mon -= 2)) {	/* 1..12 -> 11,12,1..10 */
		tm->tm_mon += 12;		/* Puts Feb last since it has leap day */
		tm->tm_year -= 1;
	}

	return (((
		(uint32_t) (tm->tm_year/4 - tm->tm_year/100 + tm->tm_year/400 + 367*tm->tm_mon/12 + tm->tm_mday) +
			tm->tm_year*365 - 719499
	    )*24 + tm->tm_hour /* now have hours */
	  )*60 + tm->tm_min /* now have minutes */
	)*60 + tm->tm_sec; /* finally seconds */	 
}



void to_tm(uint32_t tim, struct rtc_time * tm)
{
	register uint32_t    i;
	register long   hms, day;

	day = tim / SECDAY;			/* 有多少天 */
	hms = tim % SECDAY;			/* 今天的时间,单位s */

	/* Hours, minutes, seconds are easy */
	tm->tm_hour = hms / 3600;
	tm->tm_min = (hms % 3600) / 60;
	tm->tm_sec = (hms % 3600) % 60;

	/* Number of years in days */ /*算出当前年份,起始的计数年份为1970年*/
	for (i = STARTOFTIME; day >= days_in_year(i); i++) {
		day -= days_in_year(i);
	}
	tm->tm_year = i;

	/* Number of months in days left */ /*计算当前的月份*/
	if (leapyear(tm->tm_year)) {
		days_in_month(FEBRUARY) = 29;
	}
	for (i = 1; day >= days_in_month(i); i++) {
		day -= days_in_month(i);
	}
	days_in_month(FEBRUARY) = 28;
	tm->tm_mon = i;

	/* Days are what is left over (+1) from all that. *//*计算当前日期*/
	tm->tm_mday = day + 1;

	/*
	 * Determine the day of week
	 */
	GregorianDay(tm);
## 最后

**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。**

**因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

![img](https://img-blog.csdnimg.cn/img_convert/cc46ea24d24a2d46a665b97fa0e30080.png)

![img](https://img-blog.csdnimg.cn/img_convert/134aea8ca53f320bbb34437eabe9881d.jpeg)

![img](https://img-blog.csdnimg.cn/img_convert/965849a5d0d535b2d62b45ffeb102076.png)

 ![img](https://img-blog.csdnimg.cn/img_convert/b3d5cc044a3f983426b92b4b18efeac6.png)

![img](https://img-blog.csdnimg.cn/img_convert/93c4e9bce964cc5b5eb614531306297c.png)

![img](https://img-blog.csdnimg.cn/img_convert/6e346383729b9ba888eabe6d3e7eb63f.png)

![](https://img-blog.csdnimg.cn/img_convert/8b14790d80fa219489df48609172cc2e.png)

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!


基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值