C语言中时钟编程
1. 文章目的
由于最近在研究RTC,所以需要利用到C语言中的时间函数。本文从x1000的rtc时钟出发,研究C语言中时钟函数的使用与在rtthread中如何设置并且读取rtc时钟。
2.基本概念
2.1 UTC时间
整个地球分为二十四时区,每个时区都有自己的本地时间。在国际无线电通信场合,为了统一起见,使用一个统一的时间,称为通用协调时(UTC, Universal Time Coordinated)。UTC与格林尼治平均时(GMT, Greenwich Mean Time)一样,都与英国伦敦的本地时相同。在本文中,UTC与GMT含义完全相同。
我们可以认为格林威治时间就是时间协调时间(GMT=UTC),格林威治时间和UTC时间均用秒数来计算的。
北京时区是东八区,领先UTC八个小时,在电子邮件信头的Date域记为+0800。如果在电子邮件的信头中有这么一行:
Date: Fri, 08 Nov 2002 09:42:22 +0800
说明信件的发送地的地方时间是二○○二年十一月八号,星期五,早上九点四十二分(二十二秒),这个地方的本地时领先UTC八个小时(+0800, 就是东八区时间)。电子邮件信头的Date域使用二十四小时的时钟,而不使用AM和PM来标记上下午。
2.2 UNIX纪元时间
在计算机中看到的UTC时间都是从(1970年01月01日 0:00:00)开始计算秒数的。所看到的UTC时间那就是从1970年这个时间点起到具体时间共有多少秒。 这个秒数就是Unix时间戳。
说到UNIX时间不得不提Unix 2038 bug(Jason hatchet bug):2038年1月19日3时14分07秒,32位元系统的UNIX时间将会被重置。
32位的UNIX系统会以32位二进制数字表示时间,它们最多只能表示至协调世界时间2038年1月19日3时14分07秒(二进 制:01111111 11111111 11111111 11111111),在下一秒二进制数字会是10000000 00000000 00000000 00000000,这是负数,因此各系统会把时间误解作1901年12月13日20时45分52秒(亦有说回归到1970年)。这时可能会令软件发生问 题,导致系统瘫痪。
目前解决方案是把系统由32位转为64位系统。在64位系统下,此时间最多可以表示到292,277,026,596年12月4日15时30分08秒。
2.3 格林威治时间 (GMT)
格林尼治是英国伦敦南郊原皇家格林尼治天文台所在地,地球本初子午线的标界处,世界计算时间和经度的起点。以其海事历史、作为本初子午线的标准点、以及格林尼治时间以其命名而闻名于世。这里地势险要,风景秀丽,兼具历史和地方风情,也是伦敦在泰晤士河的东方门户。
不光是天文学家使用格林尼治时间,就是在新闻报刊上也经常出现这个名词。我们知道各地都有各地的地方时间。如果对国际上某一重大事情,用地方时间来记录,就会感到复杂不便.而且将来日子一长容易搞错。因此,天文学家就提出一个大家都能接受且又方便的记录方法,那就是以格林尼治的地方时间为标准。
以本初子午线的平子夜起算的平太阳时。又称格林尼治平时或格林尼治时间。各地的地方平时与世界时之差等于该地的地理经度。1960年以前曾作为基本时间计量系统被广泛应用。由于地球自转速率曾被认为是均匀的,因此在1960年以前,世界时被认为是一种均匀时。由于地球自转速度变化的影响,它不是一种均匀的时间系统,它与原子时或力学时都没有任何理论上的关系,只有通过观测才能对它们进行比较。后来世界时先后被历书时和原子时所取代,但在日常生活、天文导航、大地测量和宇宙飞行等方面仍属必需;同时,世界时反映地球自转速率的变化,是地球自转参数之一,仍为天文学和地球物理学的基本资料。
3.时间转换
由于机器时间不是人类能够识别的,所以要讲机器时间转换成大家都能识别的时分秒形式。
下面是一些经常用到的时间函数:
asctime(将时间和日期以字符串格式表示); ===>传入UTC(struct tm)tmp,返回char*。
ctime(将时间和日期以字符串格式表示); ===>传入(time_t)arg,返回char*。
gettimeofday(取得目前的时间); ===>传入(time_t)arg,返回tv,tz结构体传入时间,时区信息。
gmtime(取得目前时间和日期); ===>传入(time_t)arg,返回UTC(struct tm)tmp。
localtime(取得当地目前时间和日期); ===>传入time_t,返回当地(struct tm)tmp。
mktime(将时间结构数据转换成经过的秒数); ===>把(struct tm)tmp转换为UTC(time_t)arg。
settimeofday(设置目前时间); ===>通过tv,tz结构体传入时间,时区信息。
time(取得目前的时间); ===>非空参数(或返回值)接收(time_t)arg。
×××注1:char*是字符串时间格式。如:Sat Oct 28 02:10:06 2000。
×××注2:time_t是time()的返回值类型,(time_t)arg指从1970年到所指时间的秒数。
×××注3:struct tm为真实世界的表示时间方式,(struct tm)tmp是指向tm的时间。
×××注4:UTC,指标准时间。简单的讲,就是0时区的时间标准。
3.1 asctime函数
将时间和日期以字符串格式表示。
asctime()将参数time ptr所指的tm结构中的信息转换成真实世界所使用的时间日期表示方法,然后将结果以字符串形态返回。此函数已经由时区转换成当地时间,字符串格式为:“Wed Jun 30 21:49:08 1993
”
time_t timep;
time (&timep);
printf(“%s”,asctime(gmtime(&timep)));
打印出来的效果如下,打印出来的是格林威治时间:
Tue Mar 6 08:47:11 2018
3.2 ctime函数
将时间和日期以字符串格式进行表示。
该函数会将time_t类型的数据转换成真是世界所使用的时钟,结果将以字符串形态返回。
time_t timep;
time (&timep);
printf(“%s”,asctime(gmtime(&timep)));
得到的结果是本地时间:
Tue Mar 6 16:55:23 2018
3.3 gettimeofday函数
取得目前的时间
用C语言编写程序需要获得当前精确时间(1970年1月1日到现在的时间),或者为执行计时,可以使用gettimeofday()函数。
函数的原型
int gettimeofday ( struct timeval * tv , struct timezone * tz )
其参数tv是保存获取时间结果的结构体,参数tz用于保存时区结果:
struct timezone{
int tz_minuteswest;/*格林威治时间往西方的时差*/
int tz_dsttime;/*DST 时间的修正方式*/
}
timezone 参数若不使用则传入NULL即可。
而结构体timeval的定义为:
struct timeval{
long int tv_sec; // 秒数
long int tv_usec; // 微秒数
}
3.4 gmtime函数
将机器时间转换成格林威治时间的方法。然后将结果由结构tm返回。
函数的原型为:
struct tm*gmtime(const time_t*timep);
结构tm的定义为
struct tm {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
int tm_sec 代表目前秒数,正常范围为0-59,但允许至61秒
int tm_min 代表目前分数,范围0-59
int tm_hour 从午夜算起的时数,范围为0-23
int tm_mday 目前月份的日数,范围01-31
int tm_mon 代表目前月份,从一月算起,范围从0-11
int tm_year 从1900 年算起至今的年数
int tm_wday 一星期的日数,从星期一算起,范围为0-6
int tm_yday 从今年1月1日算起至今的天数,范围为0-365
int tm_isdst 日光节约时间的旗标
此函数返回的时间日期未经时区转换,而是UTC时间。
3.5 localtime函数
取得当地时间和日期。该函数的返回结果也是由tm结构体返回。该函数的参数与返回值与gmtime函数不一样的地方就是该函数返回的是当地时间。
3.6 mktime函数
将时间结构数据转换成经过的秒数,mktime()用来将参数timeptr所指的tm结构数据转换成从公元1970年1月1日0时0分0 秒算起至今的UTC时间所经过的秒数。
函数原型:
time_t mktime(strcut tm * timeptr);
基本的使用效果:
time_t timep;
strcut tm *p;
time(&timep);
printf(“time() : %d
”,timep);
p=localtime(&timep);
timep = mktime(p);
printf(“time()->localtime()->mktime():%d
”,timep);
简单的说,该函数的作用就是用来将strcut tm结构体转换成timep类型的数据。
3.7 settimeofday函数
设置系统时钟
int settimeofday ( const struct timeval *tv,const struct timezone *tz);
settimeofday()会把目前时间设成由tv所指的结构信息,当地时区信息则设成tz所指的结构。详细的说明请参考gettimeofday()。注意,只有root权限才能使用此函数修改时间。
3.8 time函数
取得目前的时间,此函数会返回从公元1970年1月1日的UTC时间从0时0分0秒算起到现在所经过的秒数。如果t 并非空指针的话,此函数也会将返回值存到t指针所指的内存。
函数原型:
int seconds= time((time_t*)NULL);
4.总结
本次实验主要分析有关c语言时钟编程的函数,为后面写rtc函数打下基础。