嵌入式开发的过程中,定时器是很重要的一部分,每个任务都需要控制他的运行周期和运行时间。在介绍Linux的定时器开发之前,先简单介绍一下其他开发方式的延时。
一、其他开发定时
- 裸机开发
裸机开发的定时比较简单粗暴,一般就是各个计时变量和标志在定时器中自加或者溢出。例如:
void TMR_IRQHandler()
{
static INT32U timecnt;
timecnt++;
if(1 == timecnt%50)
event1_flag = 1;
if(1 == timecnt%200)
event2_flag = 1;
…
}
上面这个例子是反面教材,虽然他也能实现定时操作。由于定时是一个高频率运行的函数,过多的取余运算会消耗大量的资源,特别是微妙级别的延时,会导致系统运行异常缓慢。所以定时器要减少或不用取余运算,可以在别的地方进行标志判断,或者精简取余次数。
- 操作系统开发
uCOS-II操作系统中,系统提供了这样的延时函数。一个是OSTimeDly(),一个是OSTimeDlyHMSM()。使用延时函数后,系统会释放资源给其它任务运行。
同时,对于一些需要硬延时的地方,例如需要准确性定时,可以采用和裸机开发一样的延时方法,同样需要注意不要占用太多中断资源。
二、Linux开发定时
进入正题,Linux开发和时间相关的函数如下:
-
函数sleep(unsigned int seconds)和usleep (useconds_t usec)
类似于uCos的OSTimeDly(),延时候释放资源给其他操作,直到延时结束。 -
函数gettimeofday()
#include <sys/time.h>
int gettimeofday(struct timeval*tv, struct timezone *tz);
其参数tv是保存获取时间结果的结构体。参数tz用于保存时区结果,若不使用则传入NULL即可:
struct timezone{
int tz_minuteswest;/格林威治时间往西方的时差/
int tz_dsttime;/DST 时间的修正方式/
}
#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
int main()
{
float time_use=0;
struct timeval start;
struct timeval end;
gettimeofday(&start,NULL); //gettimeofday(&start,&tz);结果一样
sleep(100);
gettimeofday(&end,NULL);
time_use=(end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec);//微秒
}
- 获取时间
通过gettimeofday()函数我们还可以获取当前的时间:
/**
*@brief 获取系统时间
*@param[int] date_time 系统时间
*@retval 0 成功
*/
void get_sys_time(DATE_TIME *date_time)
{
struct timeval tv;
struct tm *tm_time = NULL;
gettimeofday(&tv, NULL);
tm_time = localtime(&tv.tv_sec);
date_time->year = tm_time->tm_year + 1900;
date_time->month = tm_time->tm_mon + 1;
date_time->day = tm_time->tm_mday;
date_time->hour = tm_time->tm_hour;
date_time->minute = tm_time->tm_min;
date_time->second = tm_time->tm_sec;
date_time->msecond = tv.tv_usec/1000;
}