【问题标题】:How can I set a custom baud rate on Linux?如何在 Linux 上设置自定义波特率?
【发布时间】:2012-09-28 19:39:27
【问题描述】:

我想通过我在 Linux 上的串行端口与具有termios.h 中未定义的非标准波特率的设备通信。

我尝试了this post 中的“波特率别名”方法,但是当我执行我的 C 程序(我将其命名为“testprogram”)时,Linux 显示为"testprogram sets custom speed on ttyS0. This is deprecated."

我在 Google 上进行了一些搜索,似乎还有另一种(更新的?)方法可以将波特率更改为非标准值:在 http://sourceware.org/ml/libc-help/2009-06/msg00016.html 作者说 c_flag 的 @987654329 @ 必须与 BOTHER (=CBAUDEX | B0) 进行或运算。

使用这种方法,波特率直接在struct termiosc_ispeedc_ospeed 成员中设置。但是,我不知道如何在我的 C 程序中使用这种方法。正如作者所说,当我包含termios.h时,没有BOTHER定义/可用,那么应该如何设置波特率呢?

如何在不更改内核的情况下将波特率设置为非标准值?

【问题讨论】:

  • 答案将取决于硬件。您使用的是哪种串行硬件? PC 16550 UART 通过将输入时钟除以整数除数来工作。我怀疑它是否有达到 125k 的精度,因为它已经按照标准达到了 115.2k。
  • @Andy Ross:如果是原来的 1.8432 MHz(除以 16 得到 115,200),除以 15 将起作用:122,880 波特(1.7% 偏差)。
  • PicoCom(但不是PuTTY)可以与非标准波特率一起使用,也可以使用比 1.8432 MHz 的(整数)除法更高的粒度(底层硬件可能很多今天比 1980 年代更有能力)。以 360,000 波特为例,Black Magic Probe 中的辅助内置 USB 转串口转换器:picocom -b 360000 --imap lfcrlf /dev/ttyACM1。这是在Ubuntu MATE 20.04 和示波器上测试的实际波特率。

标签: linux serial-port baud-rate


【解决方案1】:

我注意到未定义 BOTHER 的情况相同。正如 Jamey Sharp 所说,您可以在 <asm/termios.h> 中找到它。只是一个警告,我想我同时遇到了包括它和常规 <termios.h> 文件在内的问题。

除此之外,我发现我拥有的 glibc 仍然无法正常工作,因为 glibc 的 tcsetattr 正在为不注意速度设置的旧式 struct termios 版本执行 ioctl。我可以通过使用新样式的 termios2 结构手动执行 ioctl 来设置自定义速度,包括 <asm/termios.h> 也应该可以使用它:

struct termios2 tio;

ioctl(fd, TCGETS2, &tio);
tio.c_cflag &= ~CBAUD;
tio.c_cflag |= BOTHER;
tio.c_ispeed = 12345;
tio.c_ospeed = 12345;
ioctl(fd, TCSETS2, &tio);

【讨论】:

  • 链接到完整的命令行程序:gist.github.com/sentinelt/3f1a984533556cf890d9
  • 如果您还尝试将sys/ioctl.hasm/termios.h 一起包含,编译器可能会抱怨重复定义:error: redefinition of 'struct termios'。在这种情况下,仅包括 asm/ioctls.hasm/termbits.h 可能会有所帮助。
  • 与非 POSIX 的事情有什么关系?我该怎么做?只定义_BSD_SOURCE?编译器什么都没有?
  • 查看unix.stackexchange.com/questions/327188/… 以获得完整的解决方案,包括所有缺失的定义
【解决方案2】:

您可以在 Linux 上使用 stty 命令设置自定义波特率。例如,要在串行端口 /dev/ttyX0 上设置自定义波特率 567890,请使用以下命令:

stty -F /dev/ttyX0 567890

【讨论】:

  • 在 linux 上它返回“无效参数”
  • @Sławek 确保您的串行/COM 端口设备支持波特率。 stty -F /dev/ttyS0 115200
  • 确实如此。它适用于 dougg3 解决方案。看起来 stty 只支持预定义的波特率。
  • 我非常怀疑这是否可行(对于非标准波特率,我得到与 Sławek 相同的结果)。你能修改你的答案吗(例如,在什么情况下它可能有效)?如果它实际上不起作用并删除它?它可能只适用于标准定义的工作:300,1200,2400,4800,9600,19200,38400,57600,115200,230400,460800,500600,576000,921600,1000000,1152000,1500000,2000000,2500000,3000000, 3500000 和 4000000
【解决方案3】:

dougg3 has this pretty much(我不能在那里发表评论)。您需要了解的主要附加事项是不相互冲突但确实提供正确原型的标题。答案是

#include <stropts.h>
#include <asm/termios.h>

之后,您可以使用 dougg3 的代码,最好在 ioctl() 调用中进行错误检查。您可能需要将它放在一个单独的 .c 文件中,以用于使用普通 termios 设置其他参数的串行端口代码的其余部分。首先进行 POSIX 操作,然后设置自定义速度,在 Raspberry Pi 的内置 UART 上可以正常工作,以获得 250k 波特率。

【讨论】:

    【解决方案4】:

    BOTHER 似乎可以从 Linux 上的 &lt;asm/termios.h&gt; 获得。从那里提取定义将是非常不可移植的,但我认为这个 API 无论如何都是不可移植的,所以它可能没有什么大的损失。

    【讨论】:

      【解决方案5】:

      对于 Mac 用户(可能也适用于某些Linux distributions

      stty ospeed 999999
      
      stty ispeed 999999
      

      【讨论】:

        【解决方案6】:

        你可以只使用普通的termios头和普通的termios结构(使用头asm/termios时与termios2相同)。

        因此,您使用 open() 打开设备并获取文件描述符,然后在 tcgetattr() 中使用它来填充您的 termios 结构。

        然后清除CBAUD 并将CBAUDEX 设置为c_cflagCBAUDEX 与 BOTHER 具有相同的值。

        设置后,您可以使用普通函数设置自定义波特率,例如cfsetspeed(),将所需的波特率指定为整数。

        【讨论】:

          【解决方案7】:

          您的主板 CPU 上有一个串行 I/O 芯片 (16650 UART)。 该芯片使用8位端口作为控制和数据总线,因此您可以通过控制和数据总线向该芯片写入命令。

          通常,应用程序在串口上执行以下步骤

          1. 在程序启动期间设置波特率、奇偶校验、编码、流控制和开始/结束序列长度。此设置可以通过 ioctl 到串行设备或“stty”命令来完成。事实上,stty 命令对那个串行设备使用 ioctl。
          2. 将数据字符写入串行设备,驱动程序将通过其 8 位数据总线将数据字符写入 UART 芯片。

          简而言之,你可以只在STTY命令中指定波特率,其他选项都保持默认,应该足够连接其他设备了。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-10-21
            • 1970-01-01
            • 2019-08-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-02-24
            相关资源
            最近更新 更多