Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.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
Linux 如何知道半双工串行线何时空闲?_Linux_Serial Port_Duplex_Wireless - Fatal编程技术网

Linux 如何知道半双工串行线何时空闲?

Linux 如何知道半双工串行线何时空闲?,linux,serial-port,duplex,wireless,Linux,Serial Port,Duplex,Wireless,我有一个实际的基于RS-232的串行端口,我使用Linux与微控制器进行无线通信。(我在连接的两端使用无线模块,而不是串行电缆) 有一个问题。整个操作必须为半双工,因为无线模块不支持全双工操作。事实上,它们在发送数据时忽略传入的数据 因此,在C语言中,我在寻找最有效、最快的代码,以便在开始将代码发送回远程之前,检测到没有来自远程发射器的数据 此外,远程设备只给我30毫秒的时间将数据发送回它,数据本身是47字节,速度是56kbps,因此检测线路静音的例程需要快速执行 我提供了一些想法,但我正在努力

我有一个实际的基于RS-232的串行端口,我使用Linux与微控制器进行无线通信。(我在连接的两端使用无线模块,而不是串行电缆)

有一个问题。整个操作必须为半双工,因为无线模块不支持全双工操作。事实上,它们在发送数据时忽略传入的数据

因此,在C语言中,我在寻找最有效、最快的代码,以便在开始将代码发送回远程之前,检测到没有来自远程发射器的数据

此外,远程设备只给我30毫秒的时间将数据发送回它,数据本身是47字节,速度是56kbps,因此检测线路静音的例程需要快速执行

我提供了一些想法,但我正在努力找出哪一个是最好的。也许有一个我甚至都不知道的函数,它工作得更好。我尝试过不同的VMIN和VTIME值,但发现自己没有成功

以下是我的代码想法:

想法1:

  char b[2]; //incoming character buffer
  int nread=1; //number of bytes read

  int fd=open(dev,O_NOCTTY | O_RDONLY | O_SYNC);
  while (nread > 0){
    nread=read(fd,b,1); //keep reading until no bytes read are reported
  }
  fclose(fd);
想法2:

  int timeout=1; //1 second timeout
  int fd=open(dev,O_NOCTTY | O_RDONLY | O_SYNC);
  time_t then=time(NULL);
  while (time(NULL) - then > timeout){
    nread=read(fd,b,1); 
    if (nread > 0){then=time(NULL);} //reset timer if at least 1 byte is read
  }
  fclose(fd);
想法3:

  char b[2]; //incoming character buffer
  int nread=1; //number of bytes read
  int numfail=0; //number of failed attempts to read bytes
  int fd=open(dev,O_NOCTTY | O_RDONLY | O_SYNC);
  while (numfail < 100){
    nread=read(fd,b,1); //keep reading until no bytes read are reported 100 consecutive times
    if (nread < 1){numfail++;}else{numfail=0;}
  }
  fclose(fd);
charb[2]//输入字符缓冲区
int nread=1//读取的字节数
int numfail=0//尝试读取字节失败的次数
int fd=打开(开发,O|u NOCTTY | O|u RDONLY | O|u SYNC);
而(numfail<100){
nread=read(fd,b,1);//继续读取,直到连续100次未报告任何字节读取
如果(nread<1){numfail++;}否则{numfail=0;}
}
fclose(fd);
第一个可能行不通的想法(除非我幸运地在这里找到一个特殊的linux驱动程序配置?)将继续检查端口是否有一个字节,直到没有找到为止,然后退出

第二个想法是设置一个字符必须进入的特定时间,如果在给定时间内没有字符到达,则该行被视为空闲。否则时钟将重置

最后一个想法是对第一个想法的扩展,只是在连续多次尝试从串行线读取一个字节失败之前,程序不会退出。如果检测到至少一个字节,尝试计数器将重置。我觉得这可能是我最好的选择,同时使用更好的VTIME和VMIN设置,但我不确定

我只需要一个功能,可以花很少的时间(最多很多微秒)来检测数据是不是由任何设备在串行线路发送

我觉得目前唯一的解决方案是创建更多的硬件,从PC收集串行数据,缓冲数据,然后硬件在将数据发送到远程单元之前检测串行线是否空闲,但我不想浪费更多的电路板和部件。我更希望有一个软件解决方案(在linux中)

有什么想法吗

为了清楚起见,远程单元使用基于8052的微控制器(型号at89S52),UART只有1字节缓存,我的计算机使用16550 UART,我认为它有14或16字节缓存

更新

我尝试了另一个更好的主意。它似乎可以在2毫秒的时间间隔内检测到线路空闲或不空闲时的变化,但我尝试在微秒级检测更多

这是我的代码:

  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <unistd.h>
  #include <fcntl.h>
  #include <sys/select.h>

  int main(int argc, char* argv[]){
    int fd=open("/dev/ttyS0",O_NOCTTY | O_RDONLY | O_SYNC);
    if (fd < 0){
        printf("Error\n");
        return -1;
    }
    long v=1;
    if (argc > 1){
      v=strtol(argv[1],NULL,10); //Custom inter-string timeout
    }
    struct timeval t={0,5000}; //set initial timeout to 5mS
    int gotsz=0; //characters received total
    int bpsz=100000; //Most # characters we want
    unsigned char b[bpsz]; //characters
    unsigned char* bp=b; //Active pointer to characters
    bpsz--; //We don't want to wreck memory that isnt ours
    fd_set f; 
    while(1){
      FD_ZERO(&f);
      FD_SET(fd,&f);
      int ret=select(fd+1,&f,NULL,NULL,&t); //check at 5mS intervals for anything
      if (ret < 0){
        printf("Error\n");
        return -1;
      }
      if (ret != 0){
        break; //Stall until anything is received.
      }
    }
    while(1){
      FD_ZERO(&f);
      FD_SET(fd,&f);
      int ret=select(fd+1,&f,NULL,NULL,&t);
      if (ret < 0){
        printf("Error\n");
        return -1;
      }
      if (ret == 0){
        break;    //Only exit loop when there are no more characters in a short time
      }
      int sz=read(fd,bp,bpsz); //fill up buffer advancing start pointer (saves use of strcpy)
      gotsz+=sz;
      bp+=sz;
      bpsz-=sz;
      t.tv_usec=v;
    }
    close(fd);
    //print all that we got in hex
    bp=b;
    printf("Got: ");
    int n;
    for (n=0;n<gotsz;n++){
        printf("%X",*bp);
        bp++;
    }
    printf("\n");
    printf("Intermediate Timeout %ld uS (%ld mS)\n",v,v/1000);
    return 0;
  }
#包括
#包括
#包括
#包括
#包括
#包括
int main(int argc,char*argv[]){
int fd=open(“/dev/ttyS0”,O|NOCTTY | O|RDONLY | O|SYNC);
如果(fd<0){
printf(“错误\n”);
返回-1;
}
长v=1;
如果(argc>1){
v=strtol(argv[1],NULL,10);//自定义字符串间超时
}
struct timeval t={05000};//将初始超时设置为5mS
int gotsz=0;//接收的字符总数
int bpsz=100000;//我们需要的大多数字符
无符号字符b[bpsz];//个字符
无符号字符*bp=b;//指向字符的活动指针
bpsz--;//我们不想破坏不是我们的记忆
fd_集f;
而(1){
FD_零和f;
FD_集(FD和f);
int ret=select(fd+1,&f,NULL,NULL,&t);//每隔5毫秒检查一次
如果(ret<0){
printf(“错误\n”);
返回-1;
}
如果(ret!=0){
break;//暂停,直到收到任何信息。
}
}
而(1){
FD_零和f;
FD_集(FD和f);
int ret=select(fd+1,&f,NULL,NULL,&t);
如果(ret<0){
printf(“错误\n”);
返回-1;
}
如果(ret==0){
break;//仅当短时间内没有更多字符时才退出循环
}
int sz=read(fd,bp,bpsz);//填充缓冲区前进开始指针(节省strcpy的使用)
gotsz+=sz;
bp+=sz;
bpsz-=sz;
t、 tv_usec=v;
}
关闭(fd);
//用十六进制打印所有我们得到的
bp=b;
printf(“Got:”);
int n;

对于(n=0;我想你应该检查调制解调器上的RTS/CTS引脚。我从来没有这样做过,所以我没有基于终端的代码提供。请看一些问题,比如我的设置中没有硬件流量控制,无线模块中没有硬件流量控制。作为参考,我使用的模块是HM TRPWell型号,早期搜索at89S52 said人员正在使用流量控制。您尚未参考手册。看起来您的下一步是,转到手册并查看制造商的建议。您还可以阅读类似的协议,例如带冲突检测的载波侦听多址访问(CSMA/CD)用于以太网。是的,人们可以用at89S52微控制器发明流量控制,但我正在将该微控制器上的UART连接到一个不支持硬件流量控制的无线模块,因此硬件流量控制不是我的选项。我假设你没有修改双方协议的选项,否则它将我们可以很容易地在每条消息的末尾添加一个字符来表示帧的结尾,并探测另一侧的每个字节,直到找到与该控制字符匹配的字符。。。