You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Qt通过USB转串口读取传感器数据并解决运行异常问题

Qt串口读取传感器数据问题修复方案

核心错误原因

  • 代码逻辑结构错误:死循环读取逻辑写在app.exec()之前,永远不会执行Qt事件循环,QSerialPort依赖事件循环处理IO事件,所以要么卡启动,要么只能用阻塞模式导致延迟
  • 串口参数未配置:打开串口后没有设置和传感器匹配的波特率、数据位、停止位、奇偶校验、流控参数,默认参数和传感器不匹配,导致数据接收异常、延迟高
  • 行处理逻辑不完善:检测到\r后直接清空全部缓存,若单次收到多帧数据会丢失后半部分

修复后的完整代码

#include <QCoreApplication>
#include <QObject>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <iostream>

class SensorReader : public QObject
{
    Q_OBJECT
public:
    explicit SensorReader(QObject *parent = nullptr) : QObject(parent) {
        // 查找目标串口
        const auto portList = QSerialPortInfo::availablePorts();
        std::cout << "Number of ports: " << portList.size() << "\n";
        QSerialPortInfo targetPort;
        bool found = false;
        for (const auto& port : portList) {
            std::cout << port.portName().toStdString() << " " << port.description().toStdString() << "\n";
            if (port.portName() == "ttyUSB0" && port.description() == "USB-Serial Controller D") {
                targetPort = port;
                found = true;
                break;
            }
        }
        if (!found) {
            std::cerr << "Target sensor port not found\n";
            exit(1);
        }
        // 配置并打开串口
        m_serial.setPort(targetPort);
        if (!m_serial.open(QIODevice::ReadOnly)) {
            std::cerr << "Failed to open serial port: " << m_serial.errorString().toStdString() << "\n";
            exit(1);
        }
        // ************************
        // 此处替换为你传感器的实际参数,和你之前Python pyserial配置的参数保持一致
        m_serial.setBaudRate(QSerialPort::Baud9600); // 示例波特率,按实际修改
        m_serial.setDataBits(QSerialPort::Data8);
        m_serial.setParity(QSerialPort::NoParity);
        m_serial.setStopBits(QSerialPort::OneStop);
        m_serial.setFlowControl(QSerialPort::NoFlowControl); // 必须关闭流控,大部分传感器不支持硬件流控
        // ************************
        // 绑定数据就绪信号到处理槽
        connect(&m_serial, &QSerialPort::readyRead, this, &SensorReader::onDataReceived);
        std::cout << "Serial port opened successfully: " << m_serial.portName().toStdString() << "\n";
    }
private slots:
    void onDataReceived() {
        // 追加所有新收到的数据到缓存
        m_buffer.append(m_serial.readAll());
        // 循环处理所有完整行(避免单次收到多行)
        int crPos;
        while ((crPos = m_buffer.indexOf('\r')) != -1) {
            // 提取从开头到\r位置的一行数据
            QByteArray lineData = m_buffer.left(crPos);
            // 移除已处理的部分(包括\r)
            m_buffer = m_buffer.mid(crPos + 1);
            // 输出处理
            std::cout << "End of line\n";
            std::cout << lineData.toStdString() << "\n";
        }
    }
private:
    QSerialPort m_serial;
    QByteArray m_buffer;
};

int main(int argc, char** argv)
{
    QCoreApplication app(argc, argv);
    SensorReader reader;
    return app.exec();
}

// 单文件用qmake编译时需加此行,cmake或拆分.h/.cpp可删除
#include "main.moc"

使用说明

  • 编译时确保Qt项目配置了serialport模块,.pro文件中添加QT += serialport
  • 代码中串口参数部分必须修改为和你传感器实际参数一致,波特率等参数和之前测试正常的Python代码保持相同
  • 修复后采用Qt原生事件驱动模式,没有阻塞死循环,不会出现QSocketNotifier警告,数据接收实时性和传感器输出同步
  • 缓存处理逻辑支持单次接收多帧数据,不会丢包

内容的提问来源于stack exchange,提问作者aavv

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 02:42:03