如何从linux

时间:2017-04-17 08:52:24

标签: c++ linux serialization

我正在尝试进行串行通信应用程序。我有一个运行angstrom qt linux映像的设备。我需要为该设备编写串行代码应用程序。因为交叉编译器是为QT4.8.7设置的,所以它不包括QSerialPort。所以我跟着这个link进行串行通信,我也发现了许多很好的例子。

以下是代码:

void MainWindow::SerialOpen(QString PORT)
{
fd = open(PORT.toStdString().c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
    perror("open_port: Unable to open /dev/ttyLP0\n");
    exit(1);
}

saio.sa_handler = signal_handler_IO;
saio.sa_flags = 0;
saio.sa_restorer = NULL;
sigaction(SIGIO,&saio,NULL);

fcntl(fd, F_SETFL, FNDELAY);
fcntl(fd, F_SETOWN, getpid());
fcntl(fd, F_SETFL,  O_ASYNC );

tcgetattr(fd,&termAttr);
cfsetispeed(&termAttr,B9600);
cfsetospeed(&termAttr,B9600);
termAttr.c_cflag &= ~PARENB;
termAttr.c_cflag &= ~CSTOPB;
termAttr.c_cflag &= ~CSIZE;
termAttr.c_cflag |= CS8;
termAttr.c_cflag |= (CLOCAL | CREAD);
termAttr.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
termAttr.c_iflag &= ~(IXON | IXOFF | IXANY);
termAttr.c_oflag &= ~OPOST;
tcsetattr(fd,TCSANOW,&termAttr);
qDebug("Serial Port configured....\n");
}

阅读我正在使用:

void signal_handler_IO (int status)
{
  char buf [100];
  int n = read (fd, buf, sizeof buf);
  if(n > 0)
  {
    buf[n] = '\0';
    printf("Receive OK %s\n",buf);
  }
}

我正在使用基于事件的串行读取。我在QT创建者中很精力充沛。我面临的问题是,无论何时我发送AB或任何其他单个字符。它接收它。但是当我发送完整的字符串时,它会自动中断。看看下面的图片:

enter image description here

正如您在图片中看到的那样,它会收到p l h之类的字符,但之后我发送了hello world。它打破了它并首先收到hello然后world。我再次发送hello world,然后收到he,然后llo,然后worl,然后d。为什么会出现这种行为。请帮忙。感谢。

2 个答案:

答案 0 :(得分:3)

您正在以小块的形式接收数据。尝试在while循环中运行read函数,将所有块附加到一条消息中,如下所示:

#include <cstring> // needed for strcat.
#include <errno.h> // needed for strerror and errno
void signal_handler_IO (int status)
{
    char buf [100];
    char msg[1024];
    int n;
    int length = 0;
    while((n = read (fd, buf, (sizeof buf)-1)) > 0)
    {
        buf[n] = '\0';
        // you can add a check here to see if (length+n) < 1024
        strcat(msg, buf);
        length += n;
    }
    if(n<0)
    {
        //error handling
        //EDIT: adding error handling
        fprintf(stderr, "Error while receiving message: %s\n", strerror(errno));
        return;
    }
    printf("Receive OK: '%s'\n", msg);
}

在读取数据时需要关闭信号处理,以便不为每个新的数据块调用信号处理程序。在我们完成阅读之后,需要恢复处理程序。 编辑:感谢@MarkPlotnick提供了一个更好的屏蔽信号示例,而不是将其关闭(可能会导致竞争条件)。在调用sigactionMainWindow::SerialOpen之前添加这两行来屏蔽信号,以便在处理信号时不会再次调用处理程序:

sigemptyset(&saio.sa_mask);
sigaddset(&saio.sa_mask, SIGIO);

msg的大小只是一个示例,您可以将其设置为适合消息的任何值。此外,如果您正在使用c ++,那么最好使用std::string而不是msg的数组。

请注意(sizeof buf)-1,如果您阅读了所有字符,则数组末尾的'\0'将没有空间。

另一个编辑:在我们的聊天对话之后,当没有更多字符可供阅读时,read正在阻止(即使open被{{1}调用标志为非阻塞读取)。要解决此问题,可以先检查可读取的字节数:

O_NDELAY

答案 1 :(得分:0)

  

QT4.8.7,因此它不包括QSerialPort

您可以从源构建QSerialPort并使用它。请阅读Wiki:https://wiki.qt.io/Qt_Serial_Port