当前位置: 首页 > 知识库问答 >
问题:

读取USB串行端口时的冗余(C;Mac OSX;Arduino)

陶智
2023-03-14

我正在编写一个简单的C程序,可以从连接到我的Arduino设备的USB端口读取数据。Arduino以9600的波特率输出4字节的数据块。

我希望从Arduino到我的计算机的输入看起来像这样:

136.134.132.130.129.127.126.124.121.119.117.115.113.111.

然而,我得到了这样的结果:

271.274.281..2.4062.4022.40225.4021

问题:我如何让C程序中的输入与丢失数据/重读数据保持同步?当端口有新数据时,是否有某种标志可以告诉我的程序?

代码:

#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <sys/types.h>


int open_port(void)
{
  int fd; /* File descriptor for the port */

  fd = open("/dev/tty.usbmodemfd121", O_RDWR | O_NOCTTY | O_NDELAY);
  if (fd == -1)
  {
    perror("open_port: Unable to open /dev/tty");
  }
  else
    fcntl(fd, F_SETFL, 0);

  struct termios options;
  tcgetattr(fd,&options);
  cfsetospeed(&options,B9600);
  options.c_cflag |=(CLOCAL | CREAD);
  tcsetattr(fd, TCSANOW, &options);

  return (fd);
}


int main (){

    int i;
    for(i=0; i<50; i++){

    fcntl(open_port(), F_SETFL, FNDELAY);
    char buf[5];
    size_t nbytes;
    ssize_t bytes_read;

    nbytes = sizeof(buf);
    bytes_read = read(open_port(), buf, nbytes);
    printf("%s ", buf);
    buf[0]=0;
    }

    return 0;

}

共有1个答案

郭兴平
2023-03-14

你的程序没有正确打开串口来读取它
事实上,它在for循环的每次迭代中重复打开它两次
程序只能打开设备一次。

而不是

for (i=0; i<50; i++) {

   fcntl(open_port(), F_SETFL, FNDELAY);

   bytes_read = read(open_port(), buf, nbytes);

}

主程序的结构应该像

fd = open_port();
if (fd < 0) {
    /* handle error condition */
}
rc = fcntl(fd, F_SETFL, FNDELAY);
if (rc < 0) {
    /* handle error condition */
}
for (i=0; i<50; i++) {


   bytes_read = read(fd, buf, nbytes);
   if (bytes_read < 0) {
        /* handle error condition */
    }

}
close(fd);

你的程序太“简单”了。它只设置了几个属性,并且不费心检查系统调用的返回代码。

这应该是规范模式还是非规范(又称原始)模式(即数据是ASCII文本还是二进制)
有关串行端口的正确设置,请参阅本串行编程指南。

从USB端口读取数据

USB是一种总线
程序读取的设备是连接到该USBus的串行端口。

第二个编码问题

原始代码可能会打印垃圾数据。

nbytes = sizeof(buf);
bytes_read = read(open_port(), buf, nbytes);
printf("%s ", buf);
buf[0]=0;

read()操作返回的字节不太可能被空字节终止,因此该读取缓冲区上的字符串操作可能会超出所分配数组的界限
不会出现不当行为的代码如下:

nbytes = sizeof(buf) - 1;

bytes_read = read(fd, buf, nbytes);
if (bytes_read < 0) {
    /* handle error condition */
} else {
    buf[bytes_read] = 0; /* append terminator */
    printf("%s ", buf);
}

注意nbytes比分配的缓冲区大小少一个。
这是为了确保当read()操作返回一个满的nbytes缓冲区时,有一个可用的字节来存储字符串终止符字节。
为了提高效率nbytes应该在进入for循环之前执行,而不是在循环中执行。

 类似资料:
  • 我读了很多问题和答案,但没有找到任何解决方案。也许我的问题不对,但我需要一些指导。我在Linux中使用串行端口,从我的Arduino设备读取数据。每当我想从Arduino向Linux发送数据时,我首先发送两个字节,这表示将从Arduino发送的总字节数。我将这两个字节转换为整数值,并开始从串行端口读取数据。比如说,我想把300字节从Ardiuno发送到Linux,我只需要先写{1,44},然后用下

  • 问题内容: 我研究了许多有用的线程和一些教程,但是仍然存在一些问题,这些问题应该非常简单。作为参考,这里是我细读的一些线程: 无论如何,我有一个问题。如果我收到数据,我的代码可以正常工作。如果不这样做,则read()函数将停顿,退出程序的唯一方法是使用kill -9(注意:我使用信号处理来发信号通知线程读取串行数据以终止。这不是罪魁祸首,即使我删除了信号处理,read()调用仍然停止。我正在尝试做

  • 我做了一个python程序,从串行端口读取gps数据。GPS冰球流NMEA数据语句连续插入USB时。我的程序打开端口,然后尝试读取数据,解析它,然后将其与从Arduino提取的其他数据一起写入文本文件。 我遇到的问题是,当我第一次运行程序时,有时它无法读取数据。我放入了一些Try/Exception捕获,发现以某种方式无法从GPS串行端口读取数据 如果我点击Cntrl-C几次,这似乎可以解决它遇到

  • 我正在开发一个WPF应用程序,它将读取串行端口上的数据,对其进行解析,并将其显示在UI上。 我必须使用串行端口Buad速率-115200,数据位-8,停止位-1。 我在串行端口上每秒发送10000字节,将由我的WPF应用程序读取。 但是,在这里我面临的问题与用户界面。当我开始阅读COM端口我的UI冻结。它不允许任何人做任何事情。根据我的调查,这是由于数据的高速度。 我在不同的线程上读取com端口,

  • 问题内容: 我有一个Java程序,必须读取Arduino发送的信息。我从这里获取了Java代码。现在,我不太了解它是如何工作的,但是我尝试对其进行修改,并且得到了以下信息: 我创建一个对象串行COM口,我需要在主程序,然后我使用和当我需要它。 效果很好,Arduino获取数据并将其显示在LCD显示屏中。问题是。程序运行时,它会不断从串行端口读取数据(大约每40毫秒一次),但这并不意味着Arduin

  • 问题内容: 我以下列方式从打开的串行端口读取某些数据时遇到麻烦。我已经多次使用此代码实例,并且一切正常,但是现在,由于某种原因,我无法弄清楚,我完全无法从串行端口读取任何内容。 我能够写,并且在另一端正确接收了所有消息,但是从未收到答复(正确发送)(不,电缆都还好;)) 我用来打开串行端口的代码如下: 端口初始化后,我通过简单的write命令向其中写入一些内容。 hCom是文件描述符(没关系),并