【问题标题】:How to set a non-standard baudrate on a serial port device on Linux?如何在 Linux 上的串口设备上设置非标准波特率?
【发布时间】:2019-08-15 02:32:42
【问题描述】:

在 Linux 上设置自定义波特率的方法有哪些?

这个问题的答案必须在系统调用级别之上的用户级低级 API(ioctl 等)级别。它至少在这些情况下应该是有用的:

  1. 编写使用串行端口的基于 C 的低级用户态代码,

  2. 编写抽象串行端口功能的库,

  3. 编写内核串行端口驱动程序。

    标签: linux serial-port tty


    【解决方案1】:

    不幸的是,事情取决于驱动程序。好的驱动程序将实现以下所有方法。糟糕的驱动程序只会实现其中的一些方法。因此,您需要全部尝试。以下所有方法都在linux/drivers/tty/serial/serial_core.c 的辅助函数中实现。

    有以下 4 种选择。

    1. 标准波特率在tty->termios->c_cflag 中设置。您可以选择:

          B0
          B50
          B75
          B110
          B134
          B150
          B200
          B300
          B600
          B1200
          B1800
          B2400
          B4800
          B9600
          B19200
          B38400
          B57600
          B115200
          B230400
      
    2. 如果您需要上面未列出的费率,例如460800(根据源代码 cmets,这是内核开发人员希望死亡的已弃用 hack):

      • tty->termios->c_cflag 速度设置为B38400

      • 调用 TIOCSSERIAL ioctl 并设置 (struct serial_struct) 如下:

        serial->flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP]
        // this is an assertion, i.e. what your code must achieve, not how
        

        这会将备用速度设置为 HI: 57600, VHI: 115200, SHI: 230400, WARP: 460800

    3. 您可以使用 alt_speed 设置任意速度,如下所示:

      • tty->termios->c_cflag 速度设置为B38400。这与您选择的速度无关!

      • tty->alt_speed 中设置预期速度。当alt_speed==0 时它会被忽略。

    4. 您还可以通过设置自定义除数来任意速度速率,如下所示:

      • tty->termios->c_cflag 速度设置为B38400。这与您选择的速度无关!

        bool set_baudrate(int fd, long baudrate) {
          struct termios term;
          if (tcgetattr(fd, &term)) return false;
          term.c_cflag &= ~(CBAUD | CBAUDEX);
          term.c_cflag |= B38400;
          if (tcsetattr(fd, TCSANOW, &term)) return false;
          // cont'd below
        
      • 使用struct serial_struct 调用TIOCSSERIAL ioctl,设置如下:

        serial->flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST
        serial->custom_divisor == serial->baud_base / your_new_baudrate
        // these are assertions, i.e. what your code must achieve, not how
        

      怎么做?首先通过调用TIOCGSERIALioctl 来填充结构(包括您需要的baud_base)。然后修改它以指示新的波特率并将其设置为TIOCSSERIAL

            // cont'd
            struct serial_struct serial;
            if (ioctl(fd, TIOCGSERIAL, &serial)) return false;
            serial->flags &= ~ASYNC_SPD_MASK;
            serial->flags |= ASYNC_SPD_CUST;
            serial->custom_divisor = serial->baud_base / baudrate.
            if (ioctl(fd, TIOCSSERIAL, &serial)) return false;
            return true;
         }
      

    【讨论】:

    • 我发现的一切都是关于提高波特率,这很有帮助,但我需要支持一些具有极低波特率(大约 50)的古董设备。这个答案是否也适用于那个方向?
    • 无论采用哪种方式,它都是关于设置非标准波特率的通用答案。硬件可能不支持非常低的波特率,但值得一试。例如,FTDI 驱动程序应该接受 50 的波特率,但我不记得他们芯片中的分频器计数器有多宽。对于 50 波特输出,最简单的方法是获取任何 Arduino,然后按位进行电传。如果不存在 Baudot 行规则(它会在 ASCII 和 Baudot 之间进行转换),那么将它添加到 Linux 中可能会很酷。获得 45.5 波特率应该没有问题。查看 Curious Marc 的视频 :)
    • 谢谢!既然你在听……我们会像上面解释的那样使用像 B576000 这样的符号,还是需要其他东西?另外,使用 BOTHER 速度有什么特别的注意事项吗? (我在github.com/torvalds/linux/blob/master/include/uapi/asm-generic/…找到了设置)
    • B57600 是从哪里来的?我没有提到那个符号。请帮助我了解答案中难以理解的内容-我希望对其进行改进。这是为了清楚。你有三个选择。 #2 不适用,因为您不需要列出的四个波特率。您只能在#3 和#4 之间进行选择。然后你按照它的字母。根据 #3,您将在 tty->alt_speed 中设置预期速度。根据 #4,您将设置分隔符,如图所示,即 your_new_baudrate 将替换为 50。请帮忙。
    • 我引用的符号在我链接的 linux 标头中找到。由于您的回答没有提到使用 BOTHER 符号或标题中跟随它的任何波特率,我想我想知道是否可能有第五种方法来设置端口。对于我产生的任何困惑,我深表歉意——这只是好奇,而不是我目前需要解决的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多