日期:2014-05-16 浏览次数:20726 次
在裸机编程中,我们知道常用的三大模块,GPIO,定时器,UART(串口),前面几篇文章已经介绍了GPIO的模块与应用的分而治之的模型,还有串口通讯的统一接口,那么接下来就是定时器的操作了:
让我们想想,我们在裸机的时候,定时器一般实现什么功能?延迟(这个必须有),计数(这个很常用),超时中断(用的也挺多),那么在Linux下,我们又怎么实现他们呢?
延迟:
Linux下的延迟比较简单,和windows下编程差不多,sleep()函数,没错,就是它,在us/os中,任务的调度就发生在延迟函数下,而裸机编程我们要迟延时候,就只能在那里空转盲等,非常的浪费资源。
sleep延迟的单位是s,如果想要延迟毫秒或者微妙,就用usleep();usleep的基本单位是us(微妙),所以如果一个操作我想要延迟2ms,就值需要调用usleep(2000);就可以延迟2ms,是不是比裸机编程操作方便了很多,而且效率还高,不会浪费硬件资源在哪里盲等!
计数:
这个也很常用,我们常常要记录下一个操作,或者一个引脚的电平的长度时候,就需要使用计数功能。裸机编程下,一般都会有个寄存器存放从计时开始到现在的计数次数,我们一般通过这个方法读出寄存器里面的数值,而在Linux却完全不是这样,也是通过一个结构体,通过操作统一的函数接口来获取。
Linux下,对于时间操作有个很重要的结构体:
struct timeval { tv_sec; //秒数 tv_usec; //微妙数 }
这个结构体记录着需要计时的秒数,和微妙数,如果看过我前面串口通讯的文章的朋友,对这个结构体不陌生,我在使用select方法的时候,设置一个超时的时间,用的就是这个结构体。这个可以精确的对时间进行操作。
让我们看一段代码,怎么获取某个操作的时间长度:
#include <unistd.h> #include <stdio.h> #include <sys/time.h> int main() { struct timeval tpstart, tpend; //记录记录时间开始和结束的两个变量 double timeuse; //最后换算成double类型的,如1.23s int i = 0; //短暂延迟变量 gettimeofday(&tpstart, NULL); //记录开始计时时间tpstart for (i = 0; i < 65536; i++); //延迟一会 gettimeofday(&tpend, NULL); //记录计时结束时间tpend timeuse = 1000000 * (tpend.tv_sec - tpstart.tv_sec) + tpend.tv_usec- tpstart.tv_usec; timeuse /= 1000000; //换算成*.* s printf("processor time is %lf s\n", timeuse); return 0; }这个程序很简单,可能大家不理解的是,gettimeofday这个函数,大家应该都知道Linux所有时间起始位1970年1月1日,00:00开始,这个函数就是计算从这个时间点,到现在的精确时间,精确到微妙,经过差值换算,就可以得到执行for语句所耗费的时间,Linux中也很多不精确计时法,只能计时到秒级,这里就不多说了。一般这样的操作可以满足大多数情况。
超时中断:
这个功能我没有在应用程序层实验过,但是在内核驱动层,却是有这个功能,我用的也不多,只是简单的介绍下:
#include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/timer.h> struct timer_list timer; //定义定时器结构体 //超时中断服务子函数 void timeout(void) { printk("<0>Time out!The data is %d\n",timer.data); } static int __init timer_init(void) { init_timer(&timer); //初始化定时器 timer.data = 5; //为了验证进入了中断 timer.expires = jiffies + (5*HZ); //设置超时时间 timer.function = timeout; //设置超时之后中断服务子程序入口 add_timer(&timer); //启动定时器 return 0; } static void __exit timer_exit(void) { del_timer(&timer); printk("Goodbye!Kernel\n"); } module_init(timer_init); module_exi