我在下面有一些代码。我使用此代码从嵌入式板的GPIO输出一些1和0(unsigned output[38]
)。
我的问题:两个输出值(1,0或0,1)之间的时间应该 416微秒,因为我在代码下面clock_nanosleep
定义,我也使用{{1为了更好的时间分辨率。但是,示波器(下图)测量显示两个输出值之间的时间 770 usec 。我想知道为什么信号之间有那么多不准确?
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,sched_priority()
几乎显示在运行我的代码之前没有消耗CPU(~1%)和内存(~0.5%)。我使用没有校准问题的电子示波器。
top
编辑:我已经读了几天clock_nanosleep()或其他nanosleep,usleep等不能保证按时醒来。它们通常提供在规定时间内睡眠代码,但唤醒进程取决于CPU。我发现绝对时间提供了更好的分辨率(#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);
}
}
}
标志)。我找到了与Maxime建议相同的解决方案。但是,当循环结束时,我的信号出现故障。在我看来,在嵌入式平台上创建PWM或数据输出的任何睡眠功能都不好。花一些时间来学习平台提供的CPU定时器以生成具有良好精度的PWM或数据输出是很好的。
答案 0 :(得分:2)
我无法弄清楚对clock_getres()的调用如何解决您的问题。在手册页中,据说只读取时钟的分辨率。
正如杰夫所说,使用绝对睡眠时钟应该是更好的解决方案。这可以避免来自其他代码的不期望的定时延迟。
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
}
我在少数程序上使用它来生成以太网上的常规消息。它工作正常。
答案 1 :(得分:1)
如果您正在进行时间敏感的I / O,您可能不应该使用stdio.h
中的内容,而是使用stdio完成缓冲的I / O系统调用。看起来你可能会得到最缓慢的缓冲效果,因为你的程序执行了以下步骤:
你想要的是内核在你睡觉时为写操作提供服务,而是在你睡觉之后刷新缓冲区并且你必须等待内核来处理它。
我认为最好的办法是使用open("/sys/class/gpio/gpio139/value", O_WRONLY|O_DIRECT)
来减少因缓存造成的延迟。
如果您仍需要刷新缓冲区以强制写入,则可能需要使用clock_gettime
来计算刷新数据所花费的时间并从睡眠时间中减去该时间。或者,将所需间隔添加到clock_gettime
的结果中,并将其传递给clock_nanosleep
并使用TIMER_ABSTIME
标志等待该绝对时间发生。
答案 2 :(得分:0)
我猜测问题是clock_nanosleep
正在睡眠416微秒
并且循环中的其他命令以及循环和clock_nanosleep
体系结构本身都需要354微秒。操作系统也可能提出要求。
如果设置sleep = 0,你会得到什么时间间隔?
您是在计算机还是PLC上运行它?
对评论的回应
看起来你的硬件/软件中有些东西正在做出意想不到的事情 - 它可能是一个找不到的人。
根据期间的重要程度,我有2条建议: