【问题标题】:How do I use termios.h to configure a serial port to pass raw bytes?如何使用 termios.h 配置串行端口以传递原始字节?
【发布时间】:2020-01-22 17:54:48
【问题描述】:

我需要通过 USB 虚拟串行设备与硬件进行通信。我所需要的只是使用正确的 UART 设置来回传递原始字节,我不想使用终端。使用 termios 的概念验证软件没有配置正确的位,除非我在运行前通过 stty 输入一个神奇的配置字符串,否则它不起作用。

我尝试从 stty 复制出现在 termios.h 的 POSIX 手册页中的每个设置,但它仍然不起作用,现在屏幕上充满了样板标志设置代码。

使用 termios.h 获得无终端串行端口的最低配置应该是什么?如果有任何专门针对 Linux 的补充,我需要知道这些。

【问题讨论】:

    标签: c linux unix serial-port


    【解决方案1】:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <termios.h>
    
    int serial_open(char *port, int baud)
    {
        int fd;
        struct termios tty;
        if((fd = open(port, O_RDWR | O_NOCTTY | O_SYNC)) < 0)
        {
            return -1;
        }
    
        if(tcgetattr(fd, &tty) < 0)
        {
            return -1;
        }
    
        cfsetospeed(&tty, (speed_t)baud);
        cfsetispeed(&tty, (speed_t)baud);
        tty.c_cflag |= (CLOCAL | CREAD);
        tty.c_cflag &= ~CSIZE;
        tty.c_cflag |= CS8;
        tty.c_cflag &= ~PARENB;
        tty.c_cflag |= CSTOPB;
        tty.c_cflag &= ~CRTSCTS;
        tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
        tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
        tty.c_oflag &= ~OPOST;
        tty.c_cc[VMIN] = 1;
        tty.c_cc[VTIME] = 1;
        if(tcsetattr(fd, TCSANOW, &tty))
        {
            return -1;
        }
    
        return fd;
    }
    
    /* example usage */
    int fd = serial_open("/dev/ttyUSB0", B9600);
    

    【讨论】:

    • 我的代码仍然无法正常工作,所以显然有一些我不明白的主要内容。即使程序处于活动状态,stty 也不会报告相同的设置(例如,它显示 0 波特和 CS6,这是不正确的)。我不知道不同的进程是否看到不同的设置,或者我的二进制文件在 root 下运行时是否无法设置端口。在我拆分了一些变量之后,我会回到这个问题上。不过谢谢。我会尽量保持问题和答案的一般性。
    • 我最终不得不使用cfmakeraw(),然后它就起作用了。
    【解决方案2】:

    在 Linux 上,至少函数 cfmakeraw() 将为原始 IO 设置 struct termios 串行设置 blob 中的标志。在这种情况下,删除了错误检查的工作流程如下所示:

    int fd = open(portname, O_RDWR | O_NOCTTY);
    struct termios portSettings;
    tcgetattr(fd, &portSettings);
    cfsetispeed(&portSettings, B115200);
    cfsetospeed(&portSettings, B115200);
    cfmakeraw(&portSettings);
    tcsetattr(fd, TCSANOW, &portSettings);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-22
      • 1970-01-01
      • 1970-01-01
      • 2011-03-08
      相关资源
      最近更新 更多