我基于以下结构编写了一些常用功能来管理串行端口:

  typedef struct
  {
     int  PHandle;
     unsigned int  Port;
     unsigned int  BaudRate;
     unsigned char Parity;
     unsigned char FlowControl;
     char Device[MAX_SIZE];
  } Tst_SPort;

我正在另一个文件中调用这些函数(请参见下文),以测试RS232串行端口。需要启用流控制。
  int iInit(Tst_SPort *port, const char *device, int baudRate, unsigned char parity, unsigned char flowControl)
  {
     strncpy(port->Device, device, MAX_SIZE);
     port->PHandle     = iOpen(port);
     port->Port        = -1;
     port->BaudRate    = baudRate;
     port->Parity      = parity;
     port->FlowControl = flowControl;
     if(port->PHandle > 0)
     {
        setuart(port, port->BaudRate);
     }
     return port->PHandle;
  }

  int iOpen(Tst_SPort *port)
  {
     port->PHandle = open(port->Device, O_RDWR | O_NOCTTY);
     if(port->PHandle < 0)
     {
        perror("open:");
        return (-1);
     }
     return (port->PHandle);
  }

  void setuart(Tst_SPort *port, int baudRate)
  {
     struct termios opt, optCmp;
     struct serial_struct info;

     if(port->PHandle > 0)
     {
        bzero(&opt,    sizeof(opt));
        bzero(&optCmp, sizeof(optCmp));

        if(ioctl(port->PHandle, TIOCGSERIAL, &info) == 0)
           port->Port = info.port;

        fcntl(port->PHandle, F_SETFL, O_NONBLOCK);

        if (tcgetattr(port->PHandle, &opt) < 0)
           perror("tcgetattr Get:");

        if(baudRate > 0)
        {
           cfsetospeed (&opt, baudRate);
           cfsetispeed (&opt, baudRate);
        }

        opt.c_iflag = IGNPAR;
        opt.c_oflag &= ~OPOST
        opt.c_oflag &= ~ONLCR;
        opt.c_lflag = 0;
        opt.c_cflag |= (CLOCAL | CREAD);
        opt.c_cflag &= ~(PARENB | PARODD);
        opt.c_cflag |= port->Parity;
        opt.c_cflag &= ~CSTOPB;
        opt.c_cflag &= ~CSIZE;
        opt.c_cflag |=  CS8;
        if(!port->FlowControl)
           opt.c_cflag &= ~CRTSCTS;
        else
           opt.c_cflag |= CRTSCTS;

        opt.c_cc[VMIN] = 0;
        opt.c_cc[VTIME] = 50;

        if(tcsetattr(opt->PHandle, TCSANOW, &opt) < 0)
           perror("tcgetattr Update :");

        if (tcgetattr(opt->PHandle, &optCmp) < 0)
           perror("tcgetattr Read:");

        /* Compare */
        if (memcmp((void *)&opt, (void *)&optCmp, sizeof(opt)) != 0)
           printf("Conf failed");

        tcflush(port->PHandle, TCIFLUSH);
     }
  }

  int iRead(Tst_SPort *port, char *buffer, unsigned long buffLength)
  {
     struct  timeval tv;
     fd_set  recv;
     int     s32Read = 0;
     int     s32Offset = 0;
     int     s32SRes = 0;

     tv.tv_sec = 0;
     tv.tv_usec = 100000; /* 100ms */

     if ((port) && (port->PHandle > 0))
     {
        while (s32Offset < buffLength)
        {
           FD_ZERO(&recv);
           FD_SET(port->PHandle, &recv);

           s32SRes = select(port->PHandle + 1, &recv, NULL, NULL, &tv);
           if ((s32SRes == -1) && (errno == EINTR))
           {
              continue;
           }
           else if(s32SRes > 0)
           {
              if (FD_ISSET(port->PHandle, &recv))
              {
                 s32Read = read(port->PHandle, buffer + s32Offset, buffLength - s32Offset);
                 if(s32Read  > 0)
                 {
                    tv.tv_sec = 0;
                    tv.tv_usec = 5000;
                    s32Offset += s32Read;
                    continue;
                 }
              }
           }
           break;
        }
     }
     return s32Offset;
  }

  int iClose(Tst_SPort *port)
  {
     return (close(port->Phandle));
  }

为了验证实现,引脚Tx和Rx已连接在一起,同上,适用于CTS和RTS。一切正常,发送的消息可以正确阅读。此外,当Tx与Rx断开连接时,没有读取任何内容。

但是,当将CTS从RTS上拔下时,端口关闭步骤(约20秒)后,测试块将停止。

但是,如果使用flowControl == 0调用了setuart()函数,则测试不会阻塞并立即返回预期的错误代码。

我可能对一些错误的理解,尤其是在端口配置中。这是个好方法吗?

最佳答案

您面临的问题是正确的行为。

在启用流量控制的情况下,保持CTS处于未连接状态,这意味着DTE(AKA PC)无法将数据发送到DCE(从设备)。

当您尝试写入UART输出缓冲区时,它可能已满,并且应用程序暂时停止运行,并等待直到一些缓冲区可用。

关于c - 在启用了流控制的Linux上进行串行通信-不良行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37346287/

10-15 02:10