我在下面有一些代码.我使用此代码unsigned output[38]从嵌入式板的GPIO 输出1s和0s().
我的问题:两个输出值(1,0或0,1)之间的时间应该是416微秒,正如我在clock_nanosleep下面的代码中定义的那样,我也用于sched_priority()更好的时间分辨率.但是,示波器(下图)测量显示两个输出值之间的时间是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,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);
}
}
}
Run Code Online (Sandbox Code Playgroud)

编辑:我已经读了几天clock_nanosleep()或其他nanosleep,usleep等不保证按时醒来.它们通常提供在规定时间内睡眠代码,但唤醒进程取决于CPU.我发现绝对时间提供了更好的分辨率(TIMER_ABSTIME旗帜).我找到了与Maxime建议相同的解决方案.但是,当循环结束时,我的信号出现故障.在我看来,在嵌入式平台上创建PWM或数据输出的任何睡眠功能都不好.花一些时间来学习平台提供的CPU定时器以生成具有良好精度的PWM或数据输出是很好的.
小智 3
我不知道如何调用 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
}
Run Code Online (Sandbox Code Playgroud)
我在几个程序上使用它来在以太网上生成一些常规消息。而且运行良好。