我有两个串口,一个通过主板 (/dev/ttyS0) 提供,一个通过牛津芯片 (/dev/ttyS1) 从 PCIE 到 RS232 卡 (Startech 2S952) 提供(有 /dev/ttyS2 但它没有进入这个故事)。在我的情况下如何解释波特率?
[ 1.111618] 00:03: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
[ 1.112543] 0000:08:00.0: ttyS1 at I/O 0xf010 (irq = 40, base_baud = 4000000) is a 16550A
我将逻辑分析仪连接到串行端口的 Tx/Rx 线。当我做:
stty -F /dev/ttyS0 115200
echo "ABCDEFGH" > /dev/ttyS0
然后我可以在逻辑分析仪上解码“ABCDEFGH”字符串,后跟 0x0D 0x0A,但我必须告诉它波特率为 115200。此外,当我将笔记本电脑与 USB 串行适配器(通过空调制解调器电缆)连接并读取关闭串口,只有当我将接收器设置为 115200 时,我才会得到有意义的输出。据我所知,这是应该的。
现在使用 /dev/ttyS1:
stty -F /dev/ttyS1 115200
echo "ABCDEFGH" > /dev/ttyS1
我在分析的逻辑中清楚地看到,我的消息以毫秒为单位要慢得多。事实上,它慢了大约 34.7(2) 倍,40000000/115200 = 34.7(2)。特别是,接收方膝上型计算机接收到由几个 0x00 组成的消息。当我设置为 3200 波特时,它会出现乱码。显然,该消息实际上是以 115200/34.6 = 3339.13...bps 传输的。
使用 /dev/ttyS1:
stty -F /dev/ttyS1 4000000
echo "ABCDEFGH" > /dev/ttyS1
与 /dev/ttyS1 的通信发生的位持续时间与预期的 115200 相匹配。
那么这意味着在我的情况下:
[ 1.112543] 0000:08:00.0: ttyS1 at I/O 0xf010 (irq = 40, base_baud = 4000000) is a 16550A
应该解释为“4000000”是一些内部振荡器的频率,导致在现实世界中传输 115200。我希望这个值是硬件内部的,并且隐藏在驱动程序的深处。
我错过了什么?这是我第一次使用串行端口,所以我完全迷失了。
如果我将“console=ttyS1,4000000n8”作为内核参数传递,那么我可以在笔记本电脑上设置 115200 通过串行通信。
因此,根据猜测,似乎无论出于何种原因,内核对该卡上运行的基本时钟都有错误的想法。串行端口是简单的设备,如果系统没有标准方法从卡中找出它,我不会感到惊讶。至少在某些情况下,被配置的部分是应用于基本时钟的除数,并且需要知道实际的基本时钟。
(该卡确实有用于设置最大速度的跳线,因此它可能有某种方式将设置告知支持它的驱动程序。)
无论如何,
setserial
看起来有一个baud_base
选项,我猜使用它可能有助于手动解决问题: