QT QSerialPort 的坑

本文探讨了在ARM-Linux环境下使用QSerialPort接收GPS数据遇到的问题及解决方法。指出将QSerialPort的readAll()方法置于主线程,并在子线程中进行数据解析的重要性。

最近在做ARM-LINUX GPS信息接收
4G模块是通过串口通讯的
用QSerialPort接收数据
因为数据量比较大,所以把串口接收数据的类放入了线程
结果程序莫名崩溃,一开始还以为哪里指针报错了

尝试了很久
然后我在 QSerialPort 的 readAll() 前后进行了qDebug()
发现 readAll() 后没有打印输出,那就是readAll() 出问题了

readAll()不能放入子线程

当接数据少的时候,在线程readAll()不容易出问题
因为GPS数据量大,所以才发现了这个问题,之前一直把串口放入线程接收数据

正确做法是,把readAll()放入到主线程
然后把解析的类 放入到子线程解析,通过moveToThread()
然后在emit 把 QByteArray 传入到子线程
connect的时候 末尾参数写 Qt::QueuedConnection, 这个参数意思是线程为接收槽的线程。
不写的话emit发送信号,槽接收时的线程为主线程

<think> 嗯,用户这次的需求很明确,就是要获取QT 5.14.2版本的串口通信开发资料。从引用内容看,用户显然是个开发者,正在做串口相关的项目,而且已经查阅过一些资料了——引用[2][4]都是具体的代码片段,说明用户需要的是可直接落地的技术方案。 用户特意强调版本号5.14.2,这个细节很重要。QT串口模块在不同版本间确实有差异,比如5.12之后废弃了QSerialPortInfo::standardBaudRates()。从引用[4]的代码片段看,用户应该是在Windows平台开发,因为代码里出现了convertStringToHex这样的方法,这在处理ASCII指令设备时很常见。 注意到用户提供的引用[3]里有学习资料包的线索,不过那个更像是广告。其实官方文档才是最权威的,所以我在回复里优先放上了Qt 5.14文档的链接。代码示例部分特别处理了波特率设置的版本差异问题——5.14.2需要用QSerialPort::Baud9600这样的枚举值而非数字,这个很多新手会踩。 用户没提具体应用场景,但从"串口助手"这个关键词推测,可能是要开发调试工具。所以示例代码里包含了完整的搜索端口、收发数据流程,readData()槽函数故意留白让用户自己实现业务逻辑。考虑到嵌入式开发常见需求,最后还补充了编码转换和十六进制发送的典型方案。 要不要主动问用户是否需要更多硬件交互的示例呢?比如Modbus协议解析之类的。不过先保持回复聚焦吧,后续可以根据反馈再深入。 </think> 以下是针对 **QT 5.14.2 串口通信** 的详细使用指南和示例代码,结合官方文档和最佳实践整理: --- ### **一、核心步骤与代码示例** #### 1. **工程配置** 在 `.pro` 文件中添加串口模块依赖: ```qmake QT += serialport ``` #### 2. **头文件引入** ```cpp #include <QSerialPort> #include <QSerialPortInfo> ``` --- #### 3. **获取可用串口列表** ```cpp QStringList getAvailablePorts() { QStringList ports; foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { ports << info.portName(); qDebug() << "Port:" << info.portName() << "| Description:" << info.description(); } return ports; } ``` --- #### 4. **初始化串口并连接** ```cpp QSerialPort *serial = new QSerialPort(this); // 配置串口参数 serial->setPortName("COM3"); // Windows 端口名 // serial->setPortName("/dev/ttyUSB0"); // Linux 端口名 serial->setBaudRate(QSerialPort::Baud9600); // 波特率 serial->setDataBits(QSerialPort::Data8); // 数据位 serial->setParity(QSerialPort::NoParity); // 校验位 serial->setStopBits(QSerialPort::OneStop); // 停止位 serial->setFlowControl(QSerialPort::NoFlowControl); // 流控制 // 打开串口 if (serial->open(QIODevice::ReadWrite)) { qDebug() << "串口打开成功"; connect(serial, &QSerialPort::readyRead, this, &MyClass::readData); // 连接数据接收槽 } else { qDebug() << "串口打开失败:" << serial->errorString(); } ``` --- #### 5. **数据接收槽函数** ```cpp void MyClass::readData() { QByteArray data = serial->readAll(); // 读取所有可用数据 qDebug() << "接收数据:" << data.toHex(' '); // 以十六进制打印 // 或转换为字符串: QString text = QString::fromUtf8(data); } ``` --- #### 6. **发送数据** ```cpp // 发送字符串 QString message = "Hello Serial!"; serial->write(message.toUtf8()); // 发送十六进制数据 (例如: 0xA0 0x01) QByteArray hexData = QByteArray::fromHex("A001"); serial->write(hexData); ``` --- #### 7. **关闭串口** ```cpp serial->close(); ``` --- ### **二、关键注意事项** 1. **跨平台路径差异**: - Windows:`"COM3"`, Linux:`"/dev/ttyUSB0"`, macOS:`"/dev/cu.usbserial"`。 2. **波特率设置**: - 使用 `QSerialPort::Baud9600` 等枚举值而非数字(避免兼容性问题)[^2]。 3. **数据编码**: - 设备通信常用十六进制格式,可通过 `QByteArray::toHex()` 和 `fromHex()` 转换。 4. **错误处理**: - 检查 `serial->error()` 并调用 `errorString()` 获取错误信息。 --- ### **三、完整示例代码片段** 基于引用 [4] 的代码结构简化: ```cpp // widget.h private slots: void on_btnOpen_clicked(); void on_btnSend_clicked(); void receiveData(); private: QSerialPort *m_serial; void initSerialPort(); // widget.cpp void Widget::initSerialPort() { m_serial = new QSerialPort(this); connect(m_serial, &QSerialPort::readyRead, this, &Widget::receiveData); } void Widget::on_btnOpen_clicked() { if (m_serial->isOpen()) { m_serial->close(); } else { m_serial->setPortName(ui->comboBoxPort->currentText()); m_serial->setBaudRate(QSerialPort::Baud115200); // ...其他参数配置 if (!m_serial->open(QIODevice::ReadWrite)) { qDebug() << "Error:" << m_serial->errorString(); } } } void Widget::on_btnSend_clicked() { QString text = ui->lineEditSend->text(); m_serial->write(text.toUtf8()); } void Widget::receiveData() { QByteArray data = m_serial->readAll(); ui->textEditRecv->append(QString::fromUtf8(data)); } ``` --- ### **四、资源推荐** 1. **[Qt 5.14 官方文档 - QSerialPort](https://doc.qt.io/qt-5.14/qserialport.html)** 2. **GitHub 开源项目参考**: - [QT 串口助手实现](https://github.com/search?q=qt+serial+port+example)(搜索关键词) 3. **调试工具**: - 使用虚拟串口软件(如 `com0com`)模拟设备通信。 --- ### **常见问题解决方案** - **无法检测串口**:检查系统权限(Linux需`sudo`或添加用户到`dialout`组)。 - **数据乱码**:确认设备编码格式(如UTF-8/GBK),使用 `QTextCodec` 转换。 - **接收不全**:使用 `while (serial->waitForReadyRead(50))` 循环读取剩余数据
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值