STM32使用C标准库time.h里面的时间时钟函数

标准C里面已经定义好时间日期库time.h,在嵌入式里面并没有被限制使用。下面我们看一下怎样在IAR中使用time.h库。

有四个与时间相关的类型:clock_ttime_tsize_t 和 tm。类型 clock_t、size_t 和 time_t 能够把系统时间和日期表示为某种整数。
可以通过宏定义(_DLIB_TIME_USES_LONG, _DLIB_TIME_USES_64),决定clock_t、time_t是使用32位还是64位数据类型。

Data types and constants

clock_t Data type for representing time 
time_t Data type for representing time
struct tm

Structure that holds the following data:
int tm_sec;// Sec. // 秒,正常范围从 0 到 59,但允许至 61
int tm_min;// Min // 分,范围从 0 到 59
int tm_hour;// Time // 小时,范围从 0 到 23
int tm_mday; // Day // 一月中的第几天,范围从 1 到 31
int tm_mon;// Month // 月,范围从 0 到 11
int tm_year;// Year // 自 1900 年起的年数
int tm_wday;// Day of the week // 一周中的第几天,范围从 0 到 6,从星期日算起,星期日表示为 0
int tm_yday; // Elapsed date Among from the start of the year // 一年中的第几天,范围从 0 到 365,从 1 月 1 日算起
int tm_isdst;// Season flag, such as daylight saving time // 夏令时

CLOCKS_PER_SEC The number of times an internal timing event occurs per second
STM32使用C标准库time.h里面的时间时钟函数_第1张图片

Functions that operate on time

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.

Conversion functions

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 

How to use time.h in IAR Embedded Workbench

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.

Example 1: Managing time information during debugging

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
...

Example 2: Implementation without the debugger

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.

Conclusion

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.


为了使 __time32()、__time64()和data函数工作,必须要实现 clock, __time32, __time64, and __getzone函数。
实现这些函数,并不需要重新rebuild库,我们可以在 clock.c, time.c, time64.c, and getzone.c in the arm\src\lib directory找到相关函数的模板。__getzone()默认的时区为0时区。

下面是在STM32下的测试
#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++;
    }
}


============================================================================================================

clock.c
/* 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


time.c
/*******************
 *
 * 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;
}

time64.c
/*******************
 *
 * 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

getzone.c
/*******************
 *
 * 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



你可能感兴趣的:(硬件)