QT串口QSerialPort类循环接收可能导致的数据接收不到问题。

发布时间 2023-10-11 11:07:08作者: Jeremy_CJL

QT串口QSerialPort类循环接收可能导致的数据接收不到问题。

建议在使用readAll前调用bytesAvailable来判断缓存区数据是否存在。

下面这个程序为错误示范,可能会导致串口数据一直无法读取。

QByteArray responseData;
if(m_serialport->isOpen())
{
  m_serialport->waitForReadyRead(1);
  responseData = m_serialport->readAll();//读取串口数据
  if(responseData.size() > 0)//判断读取字节数大于0
  {
    emit this->response(responseData);//发送信号给主窗口
  }
}

正确示范

QByteArray responseData;
if(m_serialport->isOpen())
{
  m_serialport->waitForReadyRead(1);
  if(m_serialport->bytesAvailable())//判断串口缓存区内部是否存在数据,存在数据再将数据读出来
  {
    responseData = m_serialport->readAll();//读取串口数据
    if(responseData.size() > 0)//判断读取字节数大于0
    {
      emit this->response(responseData);//发送信号给主窗口
    }
  }
}

 分析原因可能是QSerialPort类继承了QIODevice类,QIODevice的readAll获取到数据长度为0,但是此时恰好串口有数据进来导致状态出错,具体原因希望有大佬可以分析一下。

QIODevice::readAll()源代码实现如下:

QByteArray QIODevice::readAll()
{
    Q_D(QIODevice);
#if defined QIODEVICE_DEBUG
    printf("%p QIODevice::readAll(), d->pos = %d, d->buffer.size() = %d\n",
           this, int(d->pos), int(d->buffer.size()));
#endif

    QByteArray result;
    qint64 readBytes = 0;

    // flush internal read buffer
    if (!(d->openMode & Text) && !d->buffer.isEmpty()) {
        result = d->buffer.readAll();
        readBytes = result.size();
        d->pos += readBytes;
    }

    qint64 theSize;
    if (d->isSequential() || (theSize = size()) == 0) {
        // Size is unknown, read incrementally.
        qint64 readResult;
        do {
            result.resize(result.size() + QIODEVICE_BUFFERSIZE);
            readResult = read(result.data() + readBytes, result.size() - readBytes);
            if (readResult > 0 || readBytes == 0)
                readBytes += readResult;
        } while (readResult > 0);
    } else {
        // Read it all in one go.
        // If resize fails, don't read anything.
        result.resize(int(readBytes + theSize - d->pos));
        readBytes += read(result.data() + readBytes, result.size() - readBytes);
    }

    if (readBytes <= 0)
        result.clear();
    else
        result.resize(int(readBytes));

    return result;
}