标准C里面已经定义好时间日期库time.h,在嵌入式里面并没有被限制使用。下面我们看一下怎样在IAR中使用time.h库。
clock_t | Data type for representing time |
time_t | Data type for representing time |
struct tm | Structure that holds the following data: |
CLOCKS_PER_SEC | The number of times an internal timing event occurs per second |
clock | Returns the time elapsed since the program was started |
time | Returns the current time, as the elapsed time in seconds since 00:00:00, January 1, 1970. |
difftime | Returns the elapsed time between two times, as the difference in seconds. |
asctime | Converts a tm object to a string representation |
ctime | Converts a time_t object to a string representation |
gmtime | Converts from a time_t object to tm object |
localtime | Converts from current time to local time |
strftime | Converts a tm object into a specified format |
mktime | Converts from a tm object to a time_t object |
In embedded systems, you need to write code that calculates the date and time in order to use the time.h functions. We introduce two cases for how to use and implement the time library in IAR Embedded Workbench.
The first case is applicable when using the debugger.Time information is provided from the debugger. The information is not available when the debugger is detached from the target board. The second example shows how to manage the time without using the debugger.
If the debugger is available, the application can use the data/time library, and you do not need to implement anything else in order to manage time information. Below are two code examples: one using clock() and the other using time().
You can get the elapsed time from the system start by using a clock in the following way:
clock_t clk_time;
clk_time = clock ();
printf ("clock time:% dsec \ n", clk_time / CLOCKS_PER_SEC);
You can also use string display conversion to get the date and time:
time_t now;
struct tm * ts;
char buf [80];
now = time (NULL);
ts = localtime (& now);
strftime (buf, sizeof (buf), "% a% Y-% m-% d% H:% M:% S% Z", ts);
printf ("% s \ n", buf);
This is the result of the above code examples:
clock time: 234sec
Sat 2015-07-11 00:11:40
...
Without the debugger, the application must implement the low-level implementation of the date and time library. If you are using an RTOS, similar functions might be provided and you can use those.
The below example is for an ARM Cortex-M device, which has a Systick timer. The timer makes it easy to implement data and time functions. In this example, SysTick generates an interrupt every 1 msec.
We define two variables for time and clock and define CLOCKS_PER_SEC as ticks in one second:
#define CLOCKS_PER_SEC (1000)
clock_t clk_count = 0;
time_t time_dat;
We create an interrupt handler for the SysTick. 64bit variable is recommended for clk_count to avoid overflow. When an interrupt is generated, clk_count is incremented and time_dat is incremented if one second passes:
void SysTick_Handler (void) {
clk_count ++;
if ((clk_count% 1000) == 0) {
time_dat ++;
}
}
Two functions are implemented using variables:
clock_t clock (void) {
return (clk_count);
}
time_t __time32 (time_t * p) {
return time_dat;
}
The variable "clk_count" is initialized to 0 since clock() returns the elapsed time. The variable, "time_dat" should be initialized to the current time. We can use a conversion function to initialize it. This example uses mktime for the conversion:
struct tm orig;
orig.tm_sec = 10;
orig.tm_min = 46;
orig.tm_hour = 9;
orig.tm_mday = 10;
orig.tm_mon = 6;
orig.tm_year = 115;
orig.tm_wday = 5;
orig.tm_yday = 19;
orig.tm_isdst = -1;
time_dat = mktime (& org);
This gives the date: Fri Jul 10 09:46:10 2015
As a result, every call of the SysTick handler updates the variables. By applying these low level implementations, you can use the clock and time functions on your application.
Standard C library date and time operations implemented in time.h can be used in IAR Embedded Workbench. You can use these functions without writing a low-level implementation by using information provided by the debugger. If you want to use the library without using the debugger, you can implement low-level code as described in this article in order to use the date and time functions.
#define CLOCKS_PER_SEC (1000)
/*
可以在项目设置中设置时间使用的变量类型计数范围
_DLIB_TIME_USES_LONG
_DLIB_TIME_USES_64
*/
clock_t clk_count = 0;//系统上电后运行时间计数,如果是32位,1ms周期下最大计时49.7天
time_t time_dat;//设置localtime相对于公元1970年1月1日0时0分0秒算起至今的UTC时间所经过的秒数
/* Private functions ---------------------------------------------------------*/
clock_t clock (void) {
return (clk_count);
}
#if _DLIB_TIME_USES_64
time_t __time64 (time_t *p) {
return time_dat;
}
#else
time_t __time32 (time_t *p) {
return time_dat;
}
#endif
const char * __getzone(void)
{
return ": GMT+8:GMT+9:+0800";
}
int main(void)
{
if (SysTick_Config(SystemCoreClock / 1000))
{
/* Capture error */
while (1);
}
USART1_Config(115200);
//设置时间,localtime
{
struct tm set_time;
set_time.tm_sec = 10;
set_time.tm_min = 0;
set_time.tm_hour = 8;
set_time.tm_mday = 13;
set_time.tm_mon = 10-1;
set_time.tm_year = 2017-1900;
//set_time.tm_wday = 1;
//set_time.tm_yday = 2;
set_time.tm_isdst = -1;
//C 库函数 time_t mktime(struct tm *timeptr) 把 timeptr 所指向的结构转换为一个依据本地时区的 time_t 值,根据当前时区设置。
time_dat = mktime(&set_time);//mktime()用来将参数timeptr所指的tm结构数据转换成从公元1970年1月1日0时0分0 秒算起至今的UTC时间所经过的秒数。
}
//显示时间
{
time_t now;
struct tm* ts;
now = time(NULL);
ts = localtime(&now);
printf("localtime = %s\r\n", asctime(localtime(&now)));
printf("gmtime = %s\r\n", asctime(gmtime(&now)));
printf("ts->tm_yesr = %d\n", 1990 + ts->tm_year);
printf("ts->tm_mon = %d\n", 1 + ts->tm_mon);
printf("ts->tm_mday = %d\n", 0 + ts->tm_mday);
printf("ts->tm_hour = %d\n", 0 + ts->tm_hour);
printf("ts->tm_min = %d\n", 0 + ts->tm_min);
printf("ts->tm_sec = %d\n", 0 + ts->tm_sec);
printf("ts->tm_wday = %d\n", 0 + ts->tm_wday);
printf("ts->tm_yday = %d\n", 1 + ts->tm_yday);
printf("ctime = %s\r\n", ctime(&now));
char buf[80] = {0};
strftime (buf, sizeof (buf), "%a %Y-%m-%d %H:%M:%S%Z", ts);
printf ("%s \n", buf);
}
{
clock_t clock_start, clock_end;
printf("程序启动...\n");
clock_start = clock();
printf("休眠 5 秒...\n");
sleep(5);
clock_end = clock();
double total_t = (double)(clock_end - clock_start) / CLOCKS_PER_SEC;
printf("sleep(5) use times %f seconds\r\n", total_t);
}
{
time_t time_start, time_end;
printf("程序启动...\n");
time(&time_start);
printf("休眠 5 秒...\n");
sleep(5);
time(&time_end);
double diff_t = difftime(time_end, time_start);
printf("sleep(5) use times %f seconds\r\n", diff_t);
}
/* Display time in infinite loop */
while (1)
{
time_t now;
now = time(NULL);
printf("localtime = %s\r\n", asctime(localtime(&now)));
printf("gmtime = %s\r\n", asctime(gmtime(&now)));
sleep(5);
}
}
void SysTick_Handler(void)
{
extern clock_t clk_count;
extern time_t time_dat;
clk_count++;
if ((clk_count % 1000) == 0) {
time_dat++;
}
}
/* Copyright 1998-2010 IAR Systems AB. */
/*
* This is the default implementation of the "clock" function of the
* standard library. It can be replaced with a system-specific
* implementation.
*
* The "clock" function should return the processor time used by the
* program from some implementation-defined start time. The value
* should be such that if divided by the macro CLOCKS_PER_SEC the
* result should yield the time in seconds.
*
* The value "(clock_t)-1" means that the processor time is not
* available.
*
*/
#include
_STD_BEGIN
#pragma module_name = "?clock"
clock_t (clock)(void)
{
return ((clock_t) -1);
}
_STD_END
/*******************
*
* Copyright 1998-2010 IAR Systems AB.
*
* This is the default implementation of the "time" function of the
* standard library. It can be replaced with a system-specific
* implementation.
*
* The "time" function returns the current calendar time. (time_t)-1
* should be returned if the calendar time is not available. The time
* is measured in seconds since the first of January 1970.
*
********************/
#include
#pragma module_name = "?time"
__time32_t (__time32)(__time32_t *t)
{
if (t)
{
*t = (__time32_t) -1;
}
return (__time32_t) -1;
}
/*******************
*
* Copyright 1998-2010 IAR Systems AB.
*
* This is the default implementation of the "time" function of the
* standard library. It can be replaced with a system-specific
* implementation.
*
* The "time" function returns the current calendar time. (time_t)-1
* should be returned if the calendar time is not available. The time
* is measured in seconds since the first of January 1970.
*
********************/
#include
#pragma module_name = "?time"
#if _DLIB_TIME_ALLOW_64
__time64_t (__time64)(__time64_t *t)
{
if (t)
{
*t = (__time64_t) -1;
}
return (__time64_t) -1;
}
#endif
/*******************
*
* Copyright 2003-2010 IAR Systems AB.
*
* This is the default implementation of the __getzone. It returns
* the current time-zone, i.e. UTC.
*
*
*
*
* The return value should be a string on the following form:
*
* :[XXX[:YYY[:NNN[:DST[:DST ...]]]]]
*
* Where XXX is the standard time-zone name, YYY is the daylight
* savings time-zone name, NNN is the time zone offset, and the DSTs
* are the daylight savings time rules. Daylight savings time will add
* one hour to the normal time. (The names are only used in the 'Z'
* formatter in the strftime library function.)
*
* The time zone offset NNN is specified as a number relative to UTC,
* possibly negative (east is positive), on the format HHMM, where HH
* is hours and MM is minutes.
*
* The DSTs specifes a set of rules for how daylight savings time is
* applied. The rules must be sorted in increasing date order starting
* from the earliest date. The first rule for a specific year will
* enable DST, the next will disable it, and so on. Each rule is on
* the following form:
*
* [(YYYY)]MMDD[HH][-W|+W]
*
* (YYYY) is the first year the daylight savings rule was applied.
* It is optional. If not specified it will default to the same
* year as the previous rule or zero if no previous rule.
* MM is the month number (1-12).
* DD is the day of the month (1-31).
* HH is the hour number in a 24-hour day (optional, defaults to
* 0).
* +/-W specifies the day of the week the rule takes effect (where
* Sunday = 0, Monday = 1, etc). +W means that the rule applies
* to the first such day on or after the specified date and -W
* strictly before the date. If this is not specified, the rule
* will take effect on the exact date, regardless of the day of
* the week.
*
* On the northern hemisphere the DST rules normally comes in pairs, a
* start, Aprilish, and an end, Octoberish. On the southern hemisphere
* one normally has to use three rules: enabling DST from start of
* year, disabling it in Aprilish, and then enabling it again in
* Octoberish.
*
* Example:
*
* :GMT:GMT+1:0060:(1990)040102-0:100102-0
*
* Here, the time zone is GMT and under daylight savings time the
* time zone is named GMT+1. The time zone offset is 0060, i.e. 60
* minutes from UTC. As of the year 1990, daylight savings time
* started on the Sunday before (but not on) 1:st of April at 2am
* and ends on the first Sunday before (but not on) the first of
* October.
*
* :GMT+10:GMT+11:0900:(1990)010100-0:040102-0:100102-0
*
* Tasmania is on UTC+10 hours, with daylight savings time from
* first Sunday in October until first Sunday in April. Note, the
* first DST rule is for enabling from start of the year.
*
********************/
#include
_STD_BEGIN
char const * __getzone()
{
return ":";
}
_STD_END