【Qt】QT串口接收一帧数据有时候不完整,需要接收两次

1. 现象

c 复制代码
//正常数据
Read:  "12345678901234567890123456789012345678901234567890"		

//异常数据
Read:  "12345678901234567890123456789012"						
Read:  "345678901234567890"

2. 问题代码

c 复制代码
#include "serialbase.h"

QString serialNameLinux = "/dev/ttyS4";

SerialBase::SerialBase(QObject *parent)
    : QObject{parent}
{
    // 设置串口号
    SerialPort.setPortName(serialNameLinux);
    // 打开串口
    SerialPort.open(QIODevice::ReadWrite);
    // 设置波特率
    SerialPort.setBaudRate(115200);
    //设置数据位数
    SerialPort.setDataBits(QSerialPort::Data8);
    //设置奇偶校验
    SerialPort.setParity(QSerialPort::NoParity);
    // 设置流控制
    SerialPort.setFlowControl(QSerialPort::NoFlowControl);
    //设置停止位
    SerialPort.setStopBits(QSerialPort::OneStop);
}

SerialBase::~SerialBase()
{
    SerialPort.close();
}


void SerialBase::serialRx(void)
{
    SerialPort.waitForReadyRead(10);
    QByteArray rxBuff = SerialPort.readAll();

    if(rxBuff.length() > 0)
        qDebug() << "Read: " << rxBuff;
}

//周期性调用这个函数
void SerialBase::serialReadTest()
{
    serialRx();
}

3. 问题分析

  • 问题出在SerialPort.waitForReadyRead(10);这行代码,手册中的说明如下:
  • 超时时间到达之前接收到数据,则发送信号readyRead(),超时时间到达的时候,返回true
  • 注意,如果超时时间到达时,数据帧没有接收完,就出现了如上问题。
  • 超时时间到达时还没有数据返回,则直接返回false

4. 解决思路

接收到readyRead()信号后,再调用waitForReadyRead()等待一段时间。

4. 修改后代码

c 复制代码
#include "serialbase.h"

QString serialNameLinux = "/dev/ttyS4";

SerialBase::SerialBase(QObject *parent)
    : QObject{parent}
{
    // 设置串口号
    SerialPort.setPortName(serialNameLinux);
    // 打开串口
    SerialPort.open(QIODevice::ReadWrite);
    // 设置波特率
    SerialPort.setBaudRate(115200);
    //设置数据位数
    SerialPort.setDataBits(QSerialPort::Data8);
    //设置奇偶校验
    SerialPort.setParity(QSerialPort::NoParity);
    // 设置流控制
    SerialPort.setFlowControl(QSerialPort::NoFlowControl);
    //设置停止位
    SerialPort.setStopBits(QSerialPort::OneStop);

    //接收到数据后,再等待一段时间
    connect(&SerialPort, SIGNAL(readyRead()), this, SLOT(waitNextMs()));
}

SerialBase::~SerialBase()
{
    SerialPort.close();
}

void SerialBase::serialRx(void)
{
    SerialPort.waitForReadyRead(10);
    QByteArray rxBuff = SerialPort.readAll();

    if(rxBuff.length() > 0)
        qDebug() << "Read: " << rxBuff;
}

void SerialBase::waitNextMs()
{
    SerialPort.waitForReadyRead(20);
    qDebug() << "wait";
}

void SerialBase::serialReadTest()
{
    serialRx();
}
相关推荐
IOT-Power21 分钟前
QT 事件驱动架构
开发语言·qt·架构
umeelove353 小时前
使用 Qt 插件和 SQLCipher 实现 SQLite 数据库加密与解密
数据库·qt·sqlite
娇娇yyyyyy4 小时前
QT编程(12): QDragEvent事件
qt·microsoft
fareast_mzh4 小时前
[MySQL] Package ‘libtirpc‘, required by ‘virtual:world‘, not found
数据库·qt·mysql
IOT-Power4 小时前
Qt+C++ 控制软件架构实例
开发语言·c++·qt
Ronin3054 小时前
【Qt常用控件】输入类控件
开发语言·qt·常用控件·输入类控件
IOT-Power5 小时前
工业级大型 Qt / C++ 项目中 EventBus 的实现方式
qt
娇娇yyyyyy17 小时前
QT编程(10): QLineEdit
开发语言·qt
墨月白18 小时前
[QT]浮点数转换成4个字节的十六进制(IEEE 754标准)
qt·ieee
小温冲冲20 小时前
QML vs Qt Widgets:深度对比与选型实战指南
开发语言·c++·qt