☰
关于串口,我的物理设备接入了一个串口,我不知道它的名字是什么
2026/10/8 20:50:14 网站建设 项目流程

你可以帮我写一个程序吗,使用qt5.12.8,在银河麒麟下运行,你有什么思路吗,可以知道它是什么

QSerialPortInfo 枚举(推荐,Qt 原生)
Qt5 自带`QSerialPortInfo` ,可以列出所有串口的详细信息:

for (const QSerialPortInfo &info : QSerialPortInfo::availablePorts()) { qDebug() << info.portName(); // 如 "ttyUSB0" qDebug() << info.manufacturer(); // 厂商,如 "FTDI" qDebug() << info.description(); // 描述,如 "FT232R USB UART" qDebug() << info.vendorIdentifier(); // VID(十六进制) qDebug() << info.productIdentifier(); // PID(十六进制) qDebug() << info.serialNumber(); // 序列号 }

只要你的设备芯片是常见型号,`description` +`manufacturer` 基本就能认出来。






admin123@admin123-pc:~/桌面$ ls /dev/ttyS* /dev/ttyS0 /dev/ttyS14 /dev/ttyS2 /dev/ttyS25 /dev/ttyS30 /dev/ttyS8 /dev/ttyS1 /dev/ttyS15 /dev/ttyS20 /dev/ttyS26 /dev/ttyS31 /dev/ttyS9 /dev/ttyS10 /dev/ttyS16 /dev/ttyS21 /dev/ttyS27 /dev/ttyS4 /dev/ttyS11 /dev/ttyS17 /dev/ttyS22 /dev/ttyS28 /dev/ttyS5 /dev/ttyS12 /dev/ttyS18 /dev/ttyS23 /dev/ttyS29 /dev/ttyS6 /dev/ttyS13 /dev/ttyS19 /dev/ttyS24 /dev/ttyS3 /dev/ttyS7

你看到的这些/dev/ttyS*是 Linux 下的串口设备节点(传统8250/16550兼容串口)。你的系统里出现了ttyS0~ttyS31,说明内核最多枚举了32 个串口。

传统 8250/16550 兼容串口这是什么?

这是PC 串口通信硬件的两个经典芯片型号,后来成了"标准串口"的代名词。

名字的来源

  • 8250:1980 年代 IBM PC 上使用的第一代UART 芯片(National Semiconductor 出品)

  • 16550:1987 年推出的改进版,增加了16 字节 FIFO 缓冲区,是后来所有PC 串口的"标准"

UART =Universal Asynchronous Receiver/Transmitter(通用异步收发器),负责把并行的 CPU 数据转成串行信号发出去,反之亦然。

为什么叫"兼容"

后来几十年的串口芯片(无论哪家厂商生产),寄存器布局、编程接口都向后兼容 8250/16550。所以Linux 驱动只要认这个接口,就能驱动几乎所有传统串口。

应用层 → /dev/ttyS0 ↓ Linux 8250 驱动 (serial8250) ↓ 硬件 UART 芯片(16550 兼容) ↓ RS-232 电平 → DB9 接口 → 外部设备

典型特征

特征说明
接口形式DB9 / DB25针脚,或主板 9 针排针
电平标准RS-232(±12V)或 TTL(3.3V/5V)
地址传统固定 I/O 地址,如COM1=0x3F8, COM2=0x2F8
中断IRQ 4、IRQ 3 等
波特率通常到 115200,部分到 921600
FIFO16550 有 16 字节,8250 没有

和你/dev/ttyS*的关系

Linux 的8250驱动(代码在drivers/tty/serial/8250/)负责管理这些设备。它为每个可能的 I/O 地址/端口都建了一个/dev/ttyS*节点,所以你看到 ttyS0~ttyS31 一大串,但:

  • 真正插了硬件的 →驱动能读到芯片,显示16550A

  • 没插硬件的 → 显示unknown,纯粹是占位节点

这就是为什么你ls /dev/ttyS*看到 32 个,但实际能用的可能只有 1~2 个。




如何判断哪些是实际能用的?

.....................................待写....................................




讲讲/dev/ttyUSB*

/dev/ttyUSB*是USB 转串口设备在 Linux 下的设备节点。它和/dev/ttyS*最大的区别是:硬件不是主板上的,而是通过USB 接口热插拔接入的。

为什么会有 ttyUSB*

很多设备(单片机、PLC、传感器、路由器、Arduino等)本身只有 UART 串口,但现代电脑没有物理串口了,于是用一根USB 转串口线把UART 信号转换成 USB 信号接入电脑。

Linux 内核里的usbserial驱动负责识别这些转换芯片,并为每个转换出来的串口创建/dev/ttyUSB0、/dev/ttyUSB1……的节点。

设备 UART → USB 转串口芯片 → USB 总线 → usbserial 驱动 → /dev/ttyUSB0

常见的 USB 转串口芯片

芯片常见设备驱动模块特点
CH340 / CH341廉价Arduino、ESP开发板ch341便宜,最常见
CP2102 / CP2104ESP32、NodeMCUcp210x稳定,Silicon Labs
FT232 / FT2232工业设备、调试板ftdi_sio老牌,质量好
PL2303老式转接线pl2303早期常用,兼容性有坑
CDC ACM(非 ttyUSB)STM32、Arduino原生 USBcdc_acm节点是/dev/ttyACM*

注意:CDC 类设备不会出现在ttyUSB*,而是/dev/ttyACM*。

查看有哪些 ttyUSB:

ls /dev/ttyUSB*
admin123@admin123-pc:~/桌面$ ls /dev/ttyUSB* ls: 无法访问'/dev/ttyUSB*': 没有那个文件或目录
admin123@admin123-pc:~/桌面$ ls /dev/ttyACM* ls: 无法访问'/dev/ttyACM*': 没有那个文件或目录





使用上面的代码:

我可以识别到ttyAMA0---ttyAMA3还有ttyUSB0


你识别到的端口是什么

端口类型说明
ttyAMA0~ttyAMA3ARM SoC的 PL011 UART板载串口,常见于树莓派、瑞芯微、全志等 ARM 平台。固定编号,不随插拔变化
ttyUSB0USB 转串口你插的外接设备,通常是FTDI/CH340/CP2102等芯片。编号会变

ttyAMA*是ARM 平台特有的命名。AMA来自 ARM 的AMBA(Advanced Microcontroller Bus Architecture)总线,PL011 是这个总线上的 UART 控制器。它们对应开发板/工控板上的物理串口排针或板载接口。





打开前的检查

Qt 提供了几个有用的检查方法:

QSerialPortInfo info = /* 你选中的端口 */; // 1. 是否被占用 if (info.isBusy()) { qDebug() << "端口已被其他程序占用"; } // 2. 是否有效(有真实硬件) if (!info.isValid()) { qDebug() << "无效端口"; }



ttyAMA0 常被系统占用
在很多ARM 开发板上,ttyAMA0默认是串口控制台(内核打印、登录 shell 都走它)。程序直接打开会失败或干扰系统输出。

# 看是否被 getty 占用 systemctl status serial-getty@ttyAMA0.service # 检查内核命令行是否把 console 指向了它 cat /proc/cmdline | grep console

如果确实被占用,建议改用ttyAMA1/2/3或停掉 getty。




我看我的设备上有两个串口相关的物理接口,一个写着RS232,一个写着RS422,但我Qt程序识别出来的是ttyAMA0---ttyAMA3,感觉有点怪怪的???

你看到的“奇怪”其实是两个不同层面的东西被混淆了。你设备上物理接口写的RS232和RS422,指的是电气标准(物理层);而 Qt 识别出的ttyAMA0~3,是内核给UART 控制器分配的软件设备名。它们不是同一层面的对应关系。


为什么会有“两个物理接口,四个 ttyAMA”?

你的设备大概率是ARM 架构的开发板或工控机。ttyAMA是ARM PL011 UART 控制器的标准命名

关键在于:物理接口(RS232/RS422)和 UART 控制器(ttyAMA)之间,通常隔着一层电平转换芯片或跳线配置。


一个物理接口,背后可能对应一个或多个 UART
RS232 和 RS422 都是电气标准。RS422 需要4 根信号线来实现全双工差分传输,而 RS232 只需要2 根信号线。有些设备的 RS422 接口会占用两个 UART 控制器(一个负责发送,一个负责接收),或者通过硬件跳线将某个 UART 配置为RS422 模式。


你识别到的 4 个 ttyAMA,只有部分真正连接到了物理接口
你的设备虽然有 RS232 和 RS422 两个物理接口,但板载的ARM SoC通常有多个UART 控制器(如 4 个)。这些ttyAMA0~3可能对应 SoC 内部的4 个 UART 外设,但只有 1~2 个被引出到了物理接口上。

  • 典型的树莓派就是/dev/ttyAMA0引出到GPIO 针脚。

  • 对于工控板,厂商可能会把ttyAMA1和ttyAMA2通过板载的RS422 收发器引出。


“RS232”和“RS422”标签是给使用者看的接线指引
设备厂商在物理接口旁印上 RS232/RS422,是告诉你“这个 DB9 或端子排,电气特性符合 RS232/RS422 标准,请按对应方式接线”。它不会直接出现在 Linux 的设备节点命名里。内核只认 UART 控制器,不关心你外面接的是MAX232 芯片还是MAX490 芯片。




怎么确定哪个 ttyAMA 对应哪个物理接口?

最可靠的方法是查设备手册,因为UART到物理接口的映射是硬件设计决定的,没有通用规律。




那我应该问厂商要一下设备手册,或者直接问设备上的RS422对应着ttyAMA中的哪一个,亦或者我该从/dev目录中访问谁才能读取到另一个设备通过RS422接口发过来的串口信息?

最优先:直接问厂商

问厂商是最快、最可靠的路径。你可以直接这样问:

“我设备上有RS232 和 RS422 两个物理串口接口,请问:

它们分别对应 Linux 下的哪个/dev/ttyAMA*设备节点?

自己动手验证:从/dev里试

确认哪些 ttyAMA 是真实的

# 看每个 ttyAMA 是否有效 for i in 0 1 2 3; do echo "=== ttyAMA$i ===" stty -F /dev/ttyAMA$i -a 2>&1 | head -3 done

能正常输出参数的就是真实可用的 UART;报No such device或Invalid argument的可能未启用。

stty -F /dev/ttyAMA$i -a 2>&1 | head -3

这行是核心,拆成几部分:

部分含义
sttyset tty,查看/设置终端(串口)参数的命令
-F /dev/ttyAMA$i指定要操作的设备文件,$i替换后如/dev/ttyAMA0
-aall,显示该串口的全部当前配置
2>&1把标准错误重定向到标准输出,这样错误信息也能被管道处理
| head -3只显示输出的前 3 行,避免刷屏





今天联合调试的时候,就遇到了这种问题,我跟搞硬件的人,中间差了一些东西,让我们的沟通很艰难,我眼里只有4个串口名称:ttyAMA0---ttyAMA3,他们眼里是:我已经把线接到RS422口上了,你能不能收到数据。有点烦。。。


这种“鸡同鸭讲”的场面在软硬件联调里太常见了,你烦是完全正常的。根本原因是你们各自站在不同的抽象层说话,中间缺了一张“翻译表”。下面帮你把这个问题彻底理清。

你们各自在说什么

角色眼里的世界关心的东西
你(软件)/dev/ttyAMA0~3打开哪个设备节点、波特率、能不能读到字节
硬件同事RS422 接口、TX+/TX-、A/B 线线接对了没、电平对不对、收发器工作没

你们说的都对,但不在同一个层面。

  • 他说“我接到 RS422 口了” → 这是物理层

  • 你说“我只有 ttyAMA0~3” → 这是软件设备层

  • 中间缺的是:RS422 物理接口 ↔ 哪个 ttyAMA的映射关系


为什么沟通这么难

因为这个映射关系是硬件设计决定的,软件无法自动知道。

  • 硬件同事知道:他把线接到了 RS422 端子

  • 你知道:系统里有 4 个 ttyAMA

  • 你们都不知道(或没对齐):RS422 端子背后连的是ttyAMA ?

这个信息只存在于硬件原理图或厂商手册里,软件侧dmesg、/sys、lsusb都查不出来,因为电平转换芯片对软件是透明的。




可以尝试的方法:

现场最快的方法:你写一个最简单的测试程序,逐个 ttyAMA 监听,让硬件同事从 RS422 发数据。

用 Qt 写个最小 demo:

for (const QString &name : {"ttyAMA0", "ttyAMA1", "ttyAMA2", "ttyAMA3"}) { QSerialPort port; port.setPortName(name); port.setBaudRate(QSerialPort::Baud115200); if (port.open(QIODevice::ReadOnly)) { qDebug() << name << "打开成功,等待数据..."; // 连 readyRead 信号,收到数据就打印 } }

四个都打开,哪个收到数据,哪个就是 RS422。

但要注意:ttyAMA0很可能被内核控制台占用,打开会失败或读到内核日志,先从ttyAMA1~3试。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询