最近在写linux 下的定时器编程实验,测试发现 usleep函数在 x86 架构下的定时还是比较准确的,在arm9下 就不太准了.

今天用linux 下的setitimer()函数进行了定时 器的测试,代码如下:

 #include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <stdlib.h>
#include <signal.h>
#include <math.h>
#define pi 3.1415926 /*四元数的元素,代表估计方向 */
float q0 = , q1 = , q2 = , q3 = ;
float q0_inc,q1_inc,q2_inc,q3_inc;
/*用于对四元进行更新,角增量,不是真实的欧拉角*/
float Roll_inc,Pitch_inc,Yaw_inc;
float Roll,Pitch,Yaw; /*真实欧拉角*/ void FromEulerAngle(float Roll_add,float Pitch_add,float Yaw_add) ;
void ToEulerAngle();
void Quaternion_nor();
void Multiply(float q0_n,float q1_n,float q2_n,float q3_n); char flag=;
int count = ;
void set_timer()
{
struct itimerval itv, oldtv;
itv.it_interval.tv_sec = ;
itv.it_interval.tv_usec =;
itv.it_value.tv_sec = ;
itv.it_value.tv_usec = ; setitimer(ITIMER_REAL, &itv, &oldtv);
} void sigalrm_handler(int sig)
{
flag=; //printf("timer signal.. %d\n", count);
} int main()
{ float time_use=;
struct timeval start;
struct timeval end; signal(SIGALRM, sigalrm_handler);
set_timer();
while (count < )
{
if(flag)
{
Roll_inc=0.01;
Pitch_inc=0.01;
Yaw_inc=0.01; gettimeofday(&start,NULL); FromEulerAngle(Roll_inc,Pitch_inc,Yaw_inc) ;
/*更新四元 */
Multiply(q0_inc,q1_inc,q2_inc,q3_inc);
ToEulerAngle(); gettimeofday(&end,NULL);
time_use+=(end.tv_sec-start.tv_sec)*+(end.tv_usec-start.tv_usec);//微秒 printf("The count is %i\n",count);
printf("yaw=%f\n",Yaw*57.3);
printf("pitch=%f\n",Pitch*57.3);
printf("roll=%f\n",Roll*57.3);
flag=;
count++;
} }
printf("time_use is %f\n",time_use); exit(); } /*欧拉角转四元,其它坐标系 */
/*这里是否采用小角近似???*/ void FromEulerAngle(float Roll_add,float Pitch_add,float Yaw_add)/*这里只是机体转角近似成欧拉*/
{ /*在其他人的解算中,用的是小角近似 q=[1,Ω*t/2,Ω*t/2,Ω*t/2]T*/ float fCosHRoll = (float)cos(Roll_add * .5f);
float fSinHRoll = (float)sin(Roll_add * .5f);
float fCosHPitch = (float)cos(Pitch_add * .5f);
float fSinHPitch = (float)sin(Pitch_add * .5f);
float fCosHYaw = (float)cos(Yaw_add * .5f);
float fSinHYaw = (float)sin(Yaw_add * .5f); /*回来看看这三角函数运算用了多长时间*/
/*下面这个运算要根据坐标第进行修改*/
q0_inc = fCosHRoll * fCosHPitch * fCosHYaw + fSinHRoll * fSinHPitch * fSinHYaw;
q1_inc = fSinHRoll * fCosHPitch * fCosHYaw - fCosHRoll * fSinHPitch * fSinHYaw;
q2_inc = fCosHRoll * fSinHPitch * fCosHYaw + fSinHRoll * fCosHPitch * fSinHYaw;
q3_inc = fCosHRoll * fCosHPitch * fSinHYaw - fSinHRoll * fSinHPitch * fCosHYaw; }
/*四元数转欧拉角*/
void ToEulerAngle()
{
Roll=atan2( * (q0 * q1 + q2 * q3) , - * (q1 * q1 + q2 * q2));
Yaw = atan2( * (q0 * q3 + q1 * q2) , - * (q2 * q2 + q3 * q3));
Pitch = asin(*(q0*q2-q3*q1)) ;
} /*更新四元数*/
/* q_n 这里代表新来的四元数,这里指的是增量 */
void Multiply(float q0_n,float q1_n,float q2_n,float q3_n)
{
float q0_temp=q0*q0_n -q1*q1_n -q2*q2_n -q3*q3_n;
float q1_temp=q0*q1_n +q1*q0_n +q2*q3_n -q3*q2_n;
float q2_temp=q0*q2_n -q1*q3_n +q2*q0_n +q3*q1_n;
float q3_temp=q0*q3_n +q1*q2_n -q2*q1_n +q3*q0_n;
q0=q0_temp;
q1=q1_temp;
q2=q2_temp;
q3=q3_temp;
float s=sqrt(q0*q0+q1*q1+q2*q2+q3*q3); //这里重新进行规范化,避免的累积误差
q0=q0/s;
q1=q1/s;
q2=q2/s;
q3=q3/s; }

代码简介,我这里用的之前写的姿态解算的代码.这里进行100HZ的定时 ,在PC 上测试 10s ,运行结果如下图

其中姿态解算部分占用 3042us ,也就是说每次解算用时 3.042us  .

我在am9平台下测试,结果如下:

在freescale cortex-a9 双核 测试结果

全志  cortex-a7   双核 测试结果

这里测试结果差别还是比较大的,姿态解算用了 188213us, 平均为 0.188ms  ,相对与 10ms 的解算周期,占用还是比较小的.

补充一点,在arm9下linux 到200HZ还是可以的,但是就不太准了.这里我也同时测试了usleep函数和利用select()这个系统调用,延时都不理想.

下面介紹一下是利用RTC进行定时,下面的程序来自这里,http://www.linuxidc.com/Linux/2007-01/1821p2.htm

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h> #include <linux/rtc.h>
#include <sys/ioctl.h>
int main(int argc, char* argv[])
{
unsigned long i = ;
unsigned long data = ;
int retval = ;
int fd = open ("/dev/rtc", O_RDONLY);
if(fd < )
{
perror("open");
exit(errno);
}
/*Set the freq as 4Hz*/
if(ioctl(fd, RTC_IRQP_SET, ) < )
{
perror("ioctl(RTC_IRQP_SET)");
close(fd);
exit(errno);
}
/* Enable periodic interrupts */
if(ioctl(fd, RTC_PIE_ON, ) < )
{
perror("ioctl(RTC_PIE_ON)");
close(fd);
exit(errno);
}
for(i = ; i < ; i++)
{ /*Blocking read*/
if(read(fd, &data, sizeof(unsigned long)) < )
{
perror("read");
close(fd);
exit(errno);
}
printf("timer\n");
}
/* Disable periodic interrupts */
ioctl(fd, RTC_PIE_OFF, );
close(fd);
return ;
}

程序说明:代码第 15行处的open()函数,非root下会被拒绝访问。RTC定时有一定的局限性,频率只能为2幂。

2013.7.28,进行 posix timer 接口的编程测试,测试代码如下:

 #include <stdio.h>
#include <time.h>
#include <signal.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
char flag;
void handle(union sigval v)
{
flag=;
return;
} int create (int ms,int id)
{
timer_t tid;
struct sigevent se;
struct itimerspec ts,ots;
memset (&se,,sizeof(se));
se.sigev_notify = SIGEV_THREAD;
se.sigev_notify_function = handle;
se.sigev_value.sival_int = id; //作为handle()的参数
if(timer_create(CLOCK_REALTIME,&se,&tid)<) //create the timer
{
perror("timer_creat");
return -;
}
puts("timer_create successfully.");
ts.it_value.tv_sec = ;
ts.it_value.tv_nsec =**ms ;
ts.it_interval.tv_sec = ;
ts.it_interval.tv_nsec = **ms;
if(timer_settime (tid,TIMER_ABSTIME,&ts,&ots) < ) //start/stop the timer
{
perror("timer_settime");
return -;
}
return ;
} int main(void)
{
//create(3,1);
int num=;
create(,);
while(num<)
{
if(flag)
{
flag=;
printf("the num is %i\n",num);
num++;
} }
printf("2013.7.28.11\n");
return ;
}

代码参考百度空间,在PC 环境 下运行的时间为 10s,在arm linux下定时 200hz ,实际运行的时间为 20S,所以是极为不准确的.这期间我现时进行了 gettimeofday()这个方法的测试,结果都不理想.总结这面这些代码 ,要想进行 ms 级的精确定时 ,只有到驱动层面进行编写相关程序.

博文为本人所写,转载请表明出处:博客园:梦工厂2012.

linux 定时器编程实例(完善中).....的更多相关文章

  1. linux内核模块编程实例

    linux内核模块编程实例 学号:201400814125 班级:计科141 姓名:刘建伟 1.确定本机虚拟机中的Ubuntu下Linux的版本 通过使用命令uname -a/uname -r/una ...

  2. Linux c编程实例_例子

    例一:字符与整型变量的实现 #include <stdio.h> int main() { int c1,c2; char c3; c1='a'-'A'; c2='b'-'B'; c3=; ...

  3. Linux多线程编程实例解析

    Linux系统下的多线程遵循POSIX线程接口,称为 pthread.编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a.顺便说一下,Linux ...

  4. Linux网络编程实例解析

    **************************************************************************************************** ...

  5. Linux文件编程实例

    //捕获fopen调用中的错误 #include <stdio.h> #include <errno.h> #include <string.h> #define  ...

  6. Linux多进程编程实例

    前言:编写多进程程序时,我们应该了解一下,创建一个子进程时,操作系统内核是怎样做的.当通过fork函数创建新的子进程时,内核将父进程的用户地址空间的内容复制给子进程,这样父子进程拥有各自独立的用户空间 ...

  7. Linux管道编程实例

    /*管道 可以把管道想象为两个实体之间的单向连接器.注意,管道是半双工的, 如果需要全双工通讯,应该转而考虑套接字. 匿名管道又称管道,提供了一个进程与它的兄弟进程通讯的方法,只存在于父进程中: 命名 ...

  8. Linux 多线程编程实例

    一.多线程 VS 多进程 和进程相比,线程有很多优势.在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护代码段和数据.而运行于一个进程中的多个线程,他们之间使用相同 ...

  9. Linux shell编程 4 ---- shell中的循环

    1 for循环 1 for语句的结构 for variable in values; do statement done 2 for循环通常是用来处理一组值,这组值可以是任意的字符串的集合 3 for ...

随机推荐

  1. iframe session过期跳转到登陆页面

    在login.jsp中添加js: if(window !=top){ top.location.href=location.href; } <script type="text/jav ...

  2. Baxter机器人---测试准备(一)

    原创博文,转载请标明出处:--周学伟http://www.cnblogs.com/zxouxuewei/ baxter:http://sdk.rethinkrobotics.com/wiki/Work ...

  3. leetcode 93 Restore IP Addresses ----- java

    Given a string containing only digits, restore it by returning all possible valid IP address combina ...

  4. 20145220java程序设计第九周学习总结

    20145220java程序设计第九周学习总结 教材学习内容总结 JBDC是用于执行SQL的解决方案,开发人员使用JDBC的标准接口,数据库厂商对接口直接操作,开发人员无须接触底层数据可驱动程序的差异 ...

  5. kuangbin_ShortPath I (POJ 2240)

    本身很简单的spfa判环 TLE了一把是因为没写map(不会) 看着别人的答案临时学了一发发现只是用的话还是挺简单的 (但是绝对别学别人直接命名为m) 800多MS水过 噢对了这题Pending到超时 ...

  6. 文件的搜寻【转vbird】

    which (寻找『运行档』) [root@www ~]# which [-a] command 选项或参数: -a :将所有由 PATH 目录中可以找到的命令均列出,而不止第一个被找到的命令名称 分 ...

  7. Linux-内存管理机制、内存监控、buffer/cache异同

    在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,主要特点是,无论物理内存有多大,Linux 都将其充份利用,将 ...

  8. vc++ mfc 里保存缩放的bmp图片 不失真

    void CSaveView::OnFileSave() { BITMAP info;//原始图片 m_bitmap.GetBitmap(&info); CDC DC1; DC1.Create ...

  9. Hadoop 安装记录

    第一步:打开/etc 下面的 profile文件,在其中加入环境变量设置的代码 done JAVA_HOME=/home/hadoop/installer/jdk7u65 PATH=$JAVA_HOM ...

  10. [unity3d程序] 颜色渐变效果

    研究了下,颜色变化时遵从RGB圆环(就是说颜色条对接一下成环)路径最小变化原则.举个例子,加入ABCDE四个颜色点,并且A和E在同一点(转了一圈)设定从A变化到C的话,有两种路径,一种ABC,还一种A ...