如何在 Linux 上的串口设备上设置非标准波特率? [英] How to set a non-standard baudrate on a serial port device on Linux?
问题描述
Linux下自定义波特率有哪些方法?
What are the ways of setting custom baudrates on Linux?
此问题的答案必须在系统调用级别之上的用户级低级 API(ioctl
等)级别.至少在这些情况下它应该是有用的:
An answer to this question must be at a level of userland low-level APIs (ioctl
, etc.) above the level of a syscall. It should be useful in these circumstances at least:
编写使用串行端口的基于 C 的低级用户态代码,
Writing low-level C-based userland code that uses serial ports,
编写抽象串口功能的库,
Writing libraries that abstract the serial port functionality,
编写内核串口驱动程序.
Writing kernel serial port drivers.
推荐答案
不幸的是,事情是依赖于驱动程序的.好的驱动程序将实现以下所有方法.糟糕的驱动程序只会实现其中的一些方法.因此,您需要全部尝试.以下所有方法都在 的辅助函数中实现linux/drivers/tty/serial/serial_core.c.
Things are, unfortunately, driver-dependent. Good drivers will implement all of the methods below. Bad drivers will implement only some of the methods. Thus you need to try them all. All of the methods below are implemented in the helper functions in linux/drivers/tty/serial/serial_core.c.
有以下 4 种选择.
标准波特率在
tty->termios->c_cflag
中设置.您可以选择:
Standard baud rates are set in
tty->termios->c_cflag
. You can choose from:
B0
B50
B75
B110
B134
B150
B200
B300
B600
B1200
B1800
B2400
B4800
B9600
B19200
B38400
B57600
B115200
B230400
如果您需要上面未列出的费率,例如460800(根据源代码注释,这是内核开发人员希望死亡的已弃用黑客):
If you need rates not listed above, e.g. 460800 (this is a deprecated hack that the kernel developers wish to die, per the source code comments):
将
tty->termios->c_cflag
速度设置为B38400
调用 TIOCSSERIAL
ioctl with (struct serial_struct) 设置如下:
call TIOCSSERIAL
ioctl with (struct serial_struct) set as follows:
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
This sets alternate speed to HI: 57600, VHI: 115200, SHI: 230400, WARP: 460800
您可以使用 alt_speed 设置任意速度,如下所示:
You can set an arbitrary speed using alt_speed as follows:
将
tty->termios->c_cflag
速度设置为B38400
.这与您选择的速度无关!
Set
tty->termios->c_cflag
speed toB38400
. This is unrelated to the speed you chose!
在 tty->alt_speed
中设置预期速度.alt_speed==0
时会被忽略.
Set the intended speed in tty->alt_speed
. It gets ignored when alt_speed==0
.
您也可以通过如下设置自定义除数来任意速度:
You can also an arbitrary speed rate by setting custom divisor as follows:
将
tty->termios->c_cflag
速度设置为B38400
.这与您选择的速度无关!
Set
tty->termios->c_cflag
speed toB38400
. This is unrelated to the speed you chose!
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
调用 TIOCSSERIAL
ioctl,struct serial_struct
设置如下:
Call TIOCSSERIAL
ioctl with struct serial_struct
set as follows:
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
怎么做?首先通过调用 TIOCGSERIAL
ioctl 来填充结构(包括您需要的 baud_base
).然后修改它以指示新的波特率并使用 TIOCSSERIAL
进行设置:
How to do it? First get the structure filled (including baud_base
you need) by calling TIOCGSERIAL
ioctl. Then modify it to indicate the new baudrate and set it with 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;
}
这篇关于如何在 Linux 上的串口设备上设置非标准波特率?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!