Administrator
发布于 2025-07-27 / 11 阅读
0

QSerialPort高频率收发数据时可能存在的崩溃问题说明

#Qt

场景

  • cpu架构: arm64 天嵌TQA133

  • 系统:ubuntu18.04

  • Qt版本:Qt5.9.0

  • 波特率: 115200

代码逻辑

初始化

 m_serial = new QSerialPort();
    if(!m_serial)
    {
        qDebug("error:m_serialis null");
        return -1;
    }
    m_serial->setPortName(FileSystem::UART_EFFECT()); // 串口设备
#ifdef ARM_A40I
    m_serial->setBaudRate(57600);
#endif
#ifdef ARM_TQA133
    m_serial->setBaudRate(QSerialPort::Baud115200);
#endif
    m_serial->setDataBits(QSerialPort::Data8);
    m_serial->setParity(QSerialPort::OddParity); //因为数据发送是一个字节一个字节发送的,所以需要启用奇偶校验否则收到的数据会多出一些莫名其妙的字符
    m_serial->setStopBits(QSerialPort::OneStop);
    m_serial->setFlowControl(QSerialPort::NoFlowControl);

    if (m_serial->open(QIODevice::ReadWrite)) {
        // 连接信号和槽
        connect(m_serial, &QSerialPort::readyRead, this, &EffectSerialThread::readData);
        qDebug() << "Open effect serialport is ok";
    } else {
        qDebug() << "Open effect serialport is error";
        return 0;
    }

接收逻辑

void EffectSerialThread::readData()
{
    auto date = m_serial->readAll();
}

复现方式

  1. 每50毫秒通过使用QSerialPort通过串口向设备发送数据,当设备有数据回复过来时会触发readData槽函数,然后在槽函数中读取所有数据。

  2. 程序运行起来后十几秒到一分钟左右程序就会崩溃,从生成的core文件来看崩溃在m_serial->readAll()之中。

修复方式

  1. 取消信号槽,数据的接收不再放在槽函数。

  2. 主动通过判断m_serial->atEnd()的返回值决定是否读取数据

void EffectSerialThread::run()
{
    InitSerial();
    m_is_run = true;
    while(m_is_run)
    {
        while (!m_serial->atEnd()) {
            auto data = m_serial->read(512);
            m_data_buff.append(data);
        }
        if (!m_data_buff.isEmpty()) {
//            SPG_INFO("data buff size:" << m_data_buff.size())
            readData();
        }
        if((!mTxData_Queue.empty() || !mTxVersion_Queue.empty())&&m_bUartComplete)
        {
            if (m_is_init) {
                mutex.lock();
                if (mTxData_Queue.empty()) {
                    mutex.unlock();
                    msleep(50);
                    continue;
                }
                QByteArray data = mTxData_Queue.dequeue();//出队
                mutex.unlock();
                SendSerialData(data);
            } else {
                m_version_mutex.lock();
                if (mTxVersion_Queue.empty()) {
                    m_version_mutex.unlock();
                    msleep(50);
                    continue;
                }
                auto data = mTxVersion_Queue.dequeue();
                m_version_mutex.unlock();
                SendSerialData(data);
            }
            continue;
        }

        msleep(50);
    }
}