【问题标题】:Linux C serial port readingLinux C串口读取
【发布时间】:2014-03-20 08:34:35
【问题描述】:

我正在使用串行端口从设备接收数据。通信正常,但读取数据时出现问题。我正在使用 Linux (Ubuntu)。

这是我的代码:

int OpenPort(char *PortName, int *FileDesc) {
    *FileDesc = open (PortName, O_RDWR | O_NOCTTY | O_SYNC);
    if (fd < 0) {
            perror("fakap");
            return (P_OPEN_ERROR);
    }
    else return(P_OPEN_SUCCESS);

};

int SetPortAtributes (int fd, int speed, int parity) {
        struct termios tty;
        memset (&tty, 0, sizeof tty);
        if (tcgetattr (fd, &tty) != 0)
        {
                perror("error %d from tcgetattr");
                return -1;
        }

        cfsetospeed (&tty, speed);
        cfsetispeed (&tty, speed);

        tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
        // disable IGNBRK for mismatched speed tests; otherwise receive break
        // as \000 chars
        tty.c_iflag |= (IGNBRK | IGNPAR);,

        tty.c_oflag = 0;                // no remapping, no delays
        tty.c_cc[VMIN]  = 0;            // read doesn't block
        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

        tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
        tty.c_iflag &= ~(ISTRIP);
        tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
                                        // enable reading
        tty.c_cflag &= ~(PARENB | PARODD | HUPCL);      // shut off parity
        tty.c_cflag |= parity;
        tty.c_cflag &= ~CSTOPB;
        tty.c_cflag &= ~CRTSCTS;
        tty.c_lflag = 0;
        if (tcsetattr (fd, TCSANOW, &tty) != 0)
        {
                perror("error %d from tcsetattr");
                return -1;
        }
        return 0;
}

阅读部分:

void PortRead(int *FileDesc) {

    memset(&recBuff[0], 0, sizeof(recBuff)); //clear buff

    int n = read (*FileDesc, recBuff, sizeof(recBuff));  // read
    printf("n: %d \n", n);
    int i = 0;
    for(i = 0;i<n;i++) {
        recData.buf[i].b_int = recBuff[i]; // put rec buff to ANS_u type variable
    }
};

在我收到大于 8 个字节的消息之前一切正常。 read() 读取的字节数不超过 8 个,因此我必须第二次使用 read() 来读取所有数据。 当我使用 GtkTerm 时一切正常,但是在 C 实现过程中出现了问题。

【问题讨论】:

  • 呃,我们不知道recBuff是什么...
  • 其定义为 char recBuff[40]
  • 您没有检查读取返回值。如果 EINTR 发生,您将得到 n=-1 并且您的代码会忽略它(因此您重试第二次读取)。尝试检查 n==-1 并报告结果
  • 我可以用 printf() 检查 n 值,没有发生错误。

标签: c linux serial-port tty


【解决方案1】:

所以我必须第二次使用 read() 来读取所有数据。

在任何情况下,您都必须准备好第二次、第三次、第四次等时间致电read()始终。仅仅因为你知道对方已经发送了 16 个字节,你不能假设所有 16 个字节都会在一次操作中来自read()。它可能是 8+8、16*1、3+3+10 或任何其他组合,总和为 16(尽管这些组合中的大多数都极不可能)。

来自 read(2) 的手册页:

返回值

成功时,返回读取的字节数... 如果此数字小于请求的字节数,则不是错误


您还应该准备好处理 EINTR,就像已经评论过的那样。


在函数 OpenPort 中,打开的结果被分配给 *FileDesc,但检查了其他一些 fd 变量,这也应该被修复。

【讨论】:

    【解决方案2】:

    我不确定,但看起来“recBuff”是一个指向输入缓冲区的指针。

    int n = read (*FileDesc, recBuff, sizeof(recBuff));  // read
    

    如果为真,则 sizeof(recBuff) 等于 8。(指针大小为 8)。最多8个字节愿意读取是可以理解的。

    【讨论】:

    • 我将 sizeof(recBuff) 替换为常数值(16 或 20),没有帮助,但它仍然只读取 8 个字节。
    【解决方案3】:

    它可能会发生,例如因为实际上更少的字节 现在可用(可能是因为我们接近文件结尾,或者 因为我们正在从管道或终端读取),或者因为 read() 被信号中断。

    只要有可用数据就重复读取。

    另外,由于另一端是一个微控制器,它可能比您的工作站慢很多,所以当您执行 read() 时,数据可能根本不可用。当然,这是再试一次的另一个原因。

    看来你可以试试

    int n = 0, offset = 0, bytes_expected = 40;
    do 
    {
        n = read (*FileDesc, recBuff+offset, sizeof(recBuff));
        offset += num;
    
    } while (offset < bytes_expected);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多