【问题标题】:Redundancy when reading USB serial port (C;Mac OSX;Arduino)读取 USB 串口时的冗余 (C;Mac OSX;Arduino)
【发布时间】:2014-06-20 09:08:33
【问题描述】:

我正在编写一个简单的 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;

}

【问题讨论】:

    标签: c serial-port arduino


    【解决方案1】:

    您的程序没有正确地open()串行端口来读取它。
    事实上,它会在 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 文本还是二进制)?
    请参阅此Serial Programming Guide 以正确设置串行端口。

    从 USB 端口读取数据

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

    二次编码问题

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

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

    read() 操作返回的字节不太可能被 NULL 字节终止,因此对该读取缓冲区的字符串操作可能会超出分配数组的范围。
    不会行为不端的代码类似于:

    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 循环之前执行,而不是在循环内。

    【讨论】:

    • 我必须承认,我相信这个网站到处都是魔术师。非常翔实的帖子。输入现在以我希望的方式输入(除了一个小故障)谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-13
    • 1970-01-01
    • 2015-06-24
    • 2013-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多