C语言中的精确计时 [英] precise timing in C

查看:284
本文介绍了C语言中的精确计时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在下面有一些代码.我使用此代码从嵌入式板的GPIO输出一些1和0(unsigned output[38]).

I have a little code below. I use this code to output some 1s and 0s (unsigned output[38]) from a GPIO of an embedded board.

我的问题:两个输出值(1、0或0、1)之间的时间应为 416微秒,正如我在下面的代码clock_nanosleep上定义的那样,我也将sched_priority()用于更好的时间分辨率.但是,示波器测量(如下图所示)显示两个输出值之间的时间为 770 usc .我不知道为什么信号之间会有这么多的误差?

My Question: the time between two output values (1, 0 or 0, 1) should be 416 microseconds as I define on clock_nanosleep below code, I also used sched_priority() for a better time resolution. However, an oscilloscope (pic below) measurement shows that the time between the two output values are 770 usec . I wonder why do I have that much inaccuracy between the signals?

PS.板子(beagleboard)具有Linux 3.2.0-23-omap#36-Ubuntu Tue Apr 10 20:24:21 UTC 2012 armv7l armv7l armv7l GNU/Linux内核,并且具有750 MHz CPU,top显示几乎没有CPU (〜1%)和内存(〜0.5%)被消耗,然后再运行代码.我使用的电子示波器没有校准问题.

PS. the board(beagleboard) has Linux 3.2.0-23-omap #36-Ubuntu Tue Apr 10 20:24:21 UTC 2012 armv7l armv7l armv7l GNU/Linux kernel, and it has 750 MHz CPU, top shows almost no CPU(~1%) and memory(~0.5%) is consumed before I run my code. I use an electronic oscilloscope which has no calibration problem.

#include <stdio.h>
#include <stdlib.h> //exit();
#include <sched.h>
#include <time.h>

void msg_send();
struct sched_param sp;

int main(void){
      sp.sched_priority = sched_get_priority_max(SCHED_FIFO);
      sched_setscheduler(0, SCHED_FIFO, &sp);
      msg_send();
    return 0;
}

void msg_send(){
    unsigned output[38] = {0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,1}; 

    FILE *fp8;
    if ((fp8 = fopen("/sys/class/gpio/export", "w")) == NULL){  //echo 139 > export
           fprintf(stderr,"Cannot open export file: line844.\n"); fclose(fp8);exit(1);
    }
    fprintf(fp8, "%d", 139);  //pin 3
    fclose(fp8);

    if ((fp8 = fopen("/sys/class/gpio/gpio139/direction", "rb+")) == NULL){
       fprintf(stderr,"Cannot open direction file - GPIO139 - line851.\n");fclose(fp8); exit(1);
    }
    fprintf(fp8, "out");
    fclose(fp8);

   if((fp8 = fopen("/sys/class/gpio/gpio139/value", "w")) == NULL) {
        fprintf(stderr,"error in openning value\n");  fclose(fp8); exit(1);
}

struct timespec req = { .tv_sec=0, .tv_nsec = 416000 }; //416 usec

/* here is the part that my question focus*/
    while(1){
        for(i=0;i<38;i++){
        rewind(fp8);
        fprintf(fp8, "%d", output[i]);
        clock_nanosleep(CLOCK_MONOTONIC ,0, &req, NULL);

        }
    }
}

编辑:我已经读了几天的内容,clock_nanosleep()或其他nanosleep,usleep等不能保证准时醒来.它们通常提供在规定的时间内休眠代码的时间,但是唤醒进程取决于CPU.我发现绝对时间可以提供更好的分辨率(TIMER_ABSTIME标志).我发现了与Maxime建议的解决方案相同的解决方案.但是,当for循环完成时,我的信号有毛刺.在我看来,在嵌入式平台上创建PWM或数据输出对任何睡眠功能都不利.最好花一些时间来学习平台提供的CPU计时器来生成具有良好准确性的PWM或数据输出.

I have been reading for days that clock_nanosleep() or other nanosleep, usleep etc. does not guarantee the waking up on time. they usually provide to sleep the code for the defined time, but waking up the process depends on the CPU. what I found is that absolute time provides a better resolution (TIMER_ABSTIME flag). I found the same solution as Maxime suggests. however, I have a glitch on my signal when for loop is finalized. In my opinion, it is not good to any sleep functions to create a PWM or data output on an embedded platform. It is good to spend some time to learn CPU timers that platforms provide to generate the PWM or data out that has good accuracy.

推荐答案

我不知道如何调用clock_getres()可以解决您的问题.在手册页中,据说只读取时钟的分辨率.

I can't figure out how a call to clock_getres() can solve your problem. In the man page, it's said that only read the resolution of the clock.

正如Geoff所说,使用绝对睡眠时钟应该是一个更好的解决方案.这样可以避免其他代码带来意外的时序延迟.

As Geoff said, using absolute sleeping clock should be a better solution. This can avoid the unespected timing delay from other code.

struct timespec Time;
clock_gettime(CLOCK_REALTIME, &(Time));

while(1){
    Time.tv_nsec += 416000;
    if(Time.tv_nsec > 999999999){
        (Time.tv_sec)++;
        Time.tv_nsec -= 1000000000;
    }
    clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &(Time), NULL);
    //Do something
}

我在一些用于在以太网网络上生成常规消息的程序上使用了此功能.而且工作正常.

I am using this on fews programs I have for generating some regular message on ethernet network. And it's working fine.

这篇关于C语言中的精确计时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆