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

Qt6 C++中QSerialPort的readLine()串口通信异常问题

Qt6 QSerialPort 读取STM32带换行JSON数据的正确实现

先排查核心配置问题,再调整读取逻辑,以下是分步解决方案:

1. 确保串口配置与STM32完全匹配

Python能正常读取,说明硬件连接和STM32发送逻辑没问题,重点检查C++中QSerialPort的参数是否和Python端完全一致:

  • 波特率(BaudRate):比如9600、115200,必须严格对应
  • 数据位(DataBits):通常设为8位
  • 停止位(StopBits):通常设为1位
  • 奇偶校验(Parity):无校验(NoParity)
  • 流控制(FlowControl):无流控(NoFlowControl)
  • 特别注意:如果STM32发送的是\r\n而非单独的\n,QSerialPort默认以\n作为行终止符,会导致canReadLine()无法识别完整行,后续读取时需处理这类情况。

2. 线程中阻塞式读取的正确实现

既然允许在独立线程中循环阻塞,不要依赖canReadLine()的实时判断,改用waitForReadyRead()等待数据到来,再结合readLine()处理:

示例线程类代码

#include <QThread>
#include <QSerialPort>
#include <QDebug>

class SerialReaderThread : public QThread
{
    Q_OBJECT
public:
    explicit SerialReaderThread(QObject *parent = nullptr) : QThread(parent) {}

    void setPortConfig(const QString &portName, qint32 baudRate) {
        m_portName = portName;
        m_baudRate = baudRate;
    }

protected:
    void run() override {
        QSerialPort serial;
        // 配置串口参数
        serial.setPortName(m_portName);
        serial.setBaudRate(m_baudRate);
        serial.setDataBits(QSerialPort::Data8);
        serial.setStopBits(QSerialPort::OneStop);
        serial.setParity(QSerialPort::NoParity);
        serial.setFlowControl(QSerialPort::NoFlowControl);

        if (!serial.open(QIODevice::ReadOnly)) {
            qDebug() << "串口打开失败:" << serial.errorString();
            return;
        }

        qDebug() << "串口打开成功";

        // 循环阻塞读取
        while (!isInterruptionRequested()) {
            // 等待数据到来,超时设为3000ms(可按需调整)
            if (serial.waitForReadyRead(3000)) {
                QByteArray line = serial.readLine();
                if (!line.isEmpty()) {
                    // 去除多余的\r、\n等控制字符
                    line = line.trimmed();
                    emit lineReceived(line);
                } else {
                    // 调试用:读取缓冲区所有原始数据,排查问题
                    QByteArray rawData = serial.readAll();
                    qDebug() << "原始数据(十六进制):" << rawData.toHex() << "ASCII:" << rawData;
                }
            } else {
                qDebug() << "等待数据超时";
            }
        }

        serial.close();
    }

signals:
    void lineReceived(const QByteArray &line);

private:
    QString m_portName;
    qint32 m_baudRate;
};

3. 关键调试与问题排查

  • 如果readLine()仍返回空,先调用readAll()读取原始数据,通过十六进制输出确认:
    • 是否有数据传输(排除串口配置错误)
    • 换行符是\n还是\r\n,或是其他自定义终止符
  • 若为\r\n结尾,readLine()会读取包含\r的行,用trimmed()可去除多余控制字符,不影响JSON解析
  • 若数据量较大,可通过serial.setReadBufferSize(4096)调整读缓冲区大小

4. 主线程中调用线程的示例

// 主线程初始化读取线程
SerialReaderThread *readerThread = new SerialReaderThread(this);
readerThread->setPortConfig("COM3", 115200); // 替换为你的串口名和波特率
connect(readerThread, &SerialReaderThread::lineReceived, this, [=](const QByteArray &line){
    // 处理JSON数据,比如解析
    qDebug() << "收到JSON行:" << line;
    // 此处可调用QJsonDocument进行JSON解析
});
readerThread->start();

// 程序退出时记得终止线程
// readerThread->requestInterruption();
// readerThread->wait();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 04:05:21