1

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

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

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

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

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

4

1 回答 1

6

不幸的是,事情取决于驱动程序。好的驱动程序将实现以下所有方法。糟糕的驱动程序只会实现其中的一些方法。因此,您需要全部尝试。以下所有方法都在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(根据源代码注释,这是内核开发人员希望放弃的已弃用的 hack):

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

    • 调用TIOCSSERIALioctl 并将 (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
      
    • 使用 set调用TIOCSSERIALioctl,struct serial_struct如下所示:

      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
      

    怎么做?baud_base首先通过调用TIOCGSERIALioctl来填充结构(包括你需要的)。然后修改它以指示新的波特率并将其设置为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;
       }
    
于 2013-10-18T01:49:16.050 回答