Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中的精确定时_C_Linux_Time - Fatal编程技术网

C语言中的精确定时

C语言中的精确定时,c,linux,time,C,Linux,Time,下面我有一个小代码。我使用此代码从嵌入式板的GPIO输出一些1和0(无符号输出[38]) 我的问题:两个输出值(1,0或0,1)之间的时间应该416微秒正如我在代码下面的clock\u nanosleep中定义的那样,我还使用了sched\u priority()以获得更好的时间分辨率。然而,示波器(下图)测量表明两个输出值之间的时间770 usec。我想知道为什么信号之间有那么多不准确的地方 另外,该板(beagleboard)有Linux 3.2.0-23-omap 36 Ubuntu Ub

下面我有一个小代码。我使用此代码从嵌入式板的GPIO输出一些1和0(
无符号输出[38]

我的问题:两个输出值(1,0或0,1)之间的时间应该416微秒正如我在代码下面的
clock\u nanosleep
中定义的那样,我还使用了
sched\u priority()
以获得更好的时间分辨率。然而,示波器(下图)测量表明两个输出值之间的时间770 usec。我想知道为什么信号之间有那么多不准确的地方

另外,该板(beagleboard)有Linux 3.2.0-23-omap 36 Ubuntu Ubuntu周二4月10日20:24:21 UTC 2012 armv7l armv7l armv7l GNU/Linux内核,它有750 MHz的CPU,
top
显示几乎没有CPU(~1%),在我运行代码之前,内存(~0.5%)被消耗掉。我使用的电子示波器没有校准问题

#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);

        }
    }
}
#包括
#包括//退出();
#包括
#包括
void msg_send();
结构sched_参数sp;
内部主(空){
sp.sched_priority=sched_get_priority_max(sched_FIFO);
调度设置调度器(0、调度FIFO和sp);
msg_send();
返回0;
}
void msg_send(){
无符号输出[38]={0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,0,1,1,0,0,1,0,1,0,1,0,0,0,1,1,0,0,1,1};
文件*fp8;
如果((fp8=fopen(“/sys/class/gpio/export”,“w”))==NULL){//echo 139>export
fprintf(stderr,“无法打开导出文件:line844。\n”);fclose(fp8);退出(1);
}
fprintf(fp8,“%d”,139);//引脚3
fclose(fp8);
如果((fp8=fopen(“/sys/class/gpio/gpio139/方向”,“rb+”)==NULL){
fprintf(stderr,“无法打开方向文件-GPIO139-line851。\n”);fclose(fp8);退出(1);
}
fprintf(fp8,“输出”);
fclose(fp8);
if((fp8=fopen(“/sys/class/gpio/gpio139/value”,“w”))==NULL){
fprintf(stderr,“打开值出错”);fclose(fp8);退出(1);
}
struct timespec req={.tv_sec=0,.tv_nsec=416000};//416 usec
/*这是我问题的重点*/
而(1){

对于(i=0;i我猜问题在于
时钟的睡眠时间为416微秒
循环中的其他命令以及循环和
clock_nanosleep
体系结构本身都需要354微秒。操作系统也可能提出要求

如果你将睡眠设置为0,你会得到什么间隔

你是在计算机上运行还是在PLC上运行

评论回复

似乎你的硬件/软件中有一些东西正在做一些意想不到的事情——这可能是一个错误

根据这段时间的关键程度,我有两个建议:

  • 低临界-在程序中输入一个数字,使循环按您想要的时间进行。但是,如果这是瞬态或时间/温度相关影响,您需要定期检查漂移
  • 高临界性-在硬件中建立一个温度稳定的振荡器。这些可以从现货中购买

  • 如果您正在执行对时间敏感的I/O,您可能不应该使用
    stdio.h
    中的内容,而应该使用I/O系统调用,因为stdio完成了缓冲。看起来您可能也会受到缓冲的最坏影响,因为您的程序执行以下步骤:

  • 填满缓冲区
  • 睡眠
  • 倒带,我相信这会刷新缓冲区
  • 您希望内核在您睡眠时为写操作提供服务,而不是在您睡眠后刷新缓冲区,您必须等待内核处理它

    我认为最好的办法是使用
    open(“/sys/class/gpio/gpio139/value”,O|WRONLY | O|u DIRECT)
    ,以最大限度地减少缓存造成的延迟


    如果仍然需要刷新缓冲区以强制写入,则可能需要使用
    clock\u gettime
    计算刷新数据所花费的时间,并从睡眠时间中减去该时间。或者,将所需的间隔添加到
    clock\u gettime
    的结果中,并将其传递到
    clock\u nanosleep
    并使用
    TIMER_ABSTIME
    标记等待绝对时间。

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

    正如Geoff所说,使用绝对休眠时钟应该是一个更好的解决方案。这可以避免来自其他代码的未经检查的时间延迟

    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
    }
    

    我在fews程序上使用它在以太网网络上生成一些常规消息。它工作得很好。

    我在运行linux的嵌入式板上运行它。我删除了“while(1)”循环中的“clock_nanosleep”行,以查看执行“rewind()”、“fprintf()”和“for()”需要多少时间在这个循环中。它需要11.1纳秒。奇怪的是,如果将20分配给“tv_nsec”,那么两个值之间的时间是102纳秒。你应该将你的解决方案放入正确的答案中(你可以回答自己的问题),并接受它为正确答案。