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