QSerialPort waitForReadyRead有数据却超时问题

工作中用到Qt串口通讯,使用方法很简单,网上很多都使用的是异步(信号槽)方式,这里记录一下同步方式调用waitForReadyRead阻塞后,明明发送数据却还是返回超时问题。

这里说的是以ASCII形式发送,也就是常见的ABCD字符

十六进制形式发送waitForReadyRead会立即响应,目前还没查到具体原因。

 

如果是ASCII形式通讯,在调用waitForReadyRead之前,先调用setReadBufferSize设置缓冲区大小。这样waitForReadyRead就不会一直阻塞直到超时了。

Qt缓冲区

QSerialPort 内部维护了一个缓冲区,当有新数据进来后会先写入缓冲区不会立即触发waitForReadyRead,当缓冲区满时waitForReadyRead才会返回true,否则返回false。

可以通过setReadBufferSize函数设置缓冲区大小,需要注意的是在没设置缓冲区大小的情况下,默认缓冲区大小是0代表缓冲区大小没有限制(https://doc.qt.io/qt-5/qserialport.html#setReadBufferSize)。

 

也就是说在waitForReadyRead没超时的情况下,发送多少数据也不会放开阻塞向下执行,直到最后超时(waitForReadyRead默认超时时间30s,-1表示永不超时https://doc.qt.io/qt-5/qserialport.html#waitForReadyRead)。

虽然waitForReadyRead函数返回false超时,但是还是可以通过readAll()函数读取到接收的数据。

 简单示例代码:

    qDebug() << argv[1];
    qDebug() << "len: " << argc;
    QString com = argv[1];
    if(argc == 1) com = "COM1";
    QSerialPort serial;
    serial.setPortName(com);
    serial.setBaudRate(QSerialPort::Baud9600); // 设置波特率
    serial.setDataBits(QSerialPort::Data8); // 设置数据位
    serial.setParity(QSerialPort::NoParity); // 设置校验位
    serial.setStopBits(QSerialPort::OneStop); // 设置停止位
    serial.setFlowControl(QSerialPort::NoFlowControl); // 设置流控制

    if(serial.open(QIODevice::ReadWrite) == false) {
        qDebug() << com << "打开失败!";
        return 1;
    }
    qDebug() << com << "打开ok.";
    serial.setReadBufferSize(10);
    serial.waitForReadyRead( 10 * 1000);

    qDebug() << "串口结束." << serial.readAll();
    serial.close();

 

posted @ 2023-11-04 10:10  耿明岩  阅读(2225)  评论(1编辑  收藏  举报
希望能帮助到你,顺利解决问题! ...G(^_−)☆