Linux环境下串口数据收发监控实践
虚拟串口环境搭建
借助 socat 工具可快速构建成对的伪终端设备,无需硬件即可模拟完整双工通信场景:
# 安装工具
sudo apt-get install socat
# 创建互联的虚拟串口对
socat -d -d PTY,link=/tmp/vcom0,raw,echo=0 PTY,link=/tmp/vcom1,raw,echo=0
执行后会得到类似 /dev/pts/5 与 /dev/pts/6 的设备路径,两者形成数据通路。
Qt端代码重构示例
以下采用异步信号槽机制,分离读写端口职责:
#include <QCoreApplication>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>
class CommAgent : public QObject {
Q_OBJECT
public:
explicit CommAgent(const QString &port, QObject *parent = nullptr)
: QObject(parent), m_channel(new QSerialPort(this)) {
m_channel->setPortName(port);
m_channel->setBaudRate(QSerialPort::Baud115200);
m_channel->setDataBits(QSerialPort::Data8);
m_channel->setParity(QSerialPort::NoParity);
m_channel->setStopBits(QSerialPort::OneStop);
m_channel->setFlowControl(QSerialPort::NoFlowControl);
}
bool activate(QIODevice::OpenMode mode) {
if (!m_channel->open(mode)) {
qWarning() << "端口开启失败:" << m_channel->errorString();
return false;
}
connect(m_channel, &QSerialPort::readyRead, this, &CommAgent::onInbound);
return true;
}
void dispatch(const QByteArray &payload) {
m_channel->write(payload);
m_channel->flush();
}
private slots:
void onInbound() {
auto chunk = m_channel->readAll();
qDebug() << "[" << m_channel->portName() << "] 收到:" << chunk;
}
private:
QSerialPort *m_channel;
};
主程序调用逻辑
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
CommAgent upstream("/tmp/vcom0", &app);
CommAgent downstream("/tmp/vcom1", &app);
if (!upstream.activate(QIODevice::WriteOnly) ||
!downstream.activate(QIODevice::ReadOnly)) {
return -1;
}
// 延迟发送确保下游就绪
QTimer::singleShot(500, &upstream, [&]() {
upstream.dispatch("HelloVirtualPort");
});
return app.exec();
}
硬件环回测试方法
对于实体串口,采用短接法验证通路完整性:
| 引脚定义 | 连接方式 |
|---|---|
| TXD (发送) | → RXD (接收) |
| GND (地) | → GND (地) |
同一端口同时承担收发角色,配置为 ReadWrite 模式:
QSerialPort loopback;
loopback.setPortName("/dev/ttyUSB0");
loopback.open(QIODevice::ReadWrite);
connect(&loopback, &QSerialPort::readyRead, [&]() {
qDebug() << "回显数据:" << loopback.readAll();
});
loopback.write("LoopCheck");
loopback.flush();
辅助诊断工具集
终端监控:
# 十六进制模式查看原始字节流
minicom -D /dev/ttyUSB0 -b 115200 --hex
# 使用 picocom 替代方案
picocom --baud 115200 --imap lfcrlf /dev/pts/5
权限快速修复:
# 当前用户加入 dialout 组,注销后生效
sudo usermod -a -G dialout $USER
# 临时提权
sudo chmod 666 /dev/ttyUSB0
异常排查要点
- 确认端口未被占用:
lsof | grep /dev/ttyUSB0 - 校验波特率、数据位、停止位、校验位四元组一致性
- 流控设置为
NoFlowControl避免 RTS/CTS 信号阻塞 - 适当追加
QThread::msleep(20)等待硬件缓冲排空