QSerialPort的waitForReadyRead调用超时问题

文章介绍了在Qt环境下使用QSerialPort进行串口通信时遇到的waitForReadyRead超时问题。通过官方示例,解释了不应该在readyRead信号的槽函数内部再次调用waitForReadyRead,而应该使用定时的串口接收方法。此外,还提供了两种不同的策略:一种是设定固定长度或超时后结束接收,另一种是在未收到响应时重发数据,最多重试5次。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写串口收发函数的时候调用waitForReadyRead老是发生超时问题,对比了官方参考示例,不能再connect(&serialPort, SIGNAL(readyRead()), this, SLOT(serialPortReadyRead())); 的serialPortReadyRead()里再调用waitForReadyRead了,一定是超时的。

下面是官方例程,官方再不定时的串口接收使用connect(&serialPort, SIGNAL(readyRead()),…)
定时的串口接收使用serialPort.waitForReadyRead(…)
没有connect的槽函数里再用waitForReadyRead的

#include <QCoreApplication>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QSerialPort serialPort;
    serialPort.setPortName("/dev/tty0"); // Replace with the name of your serial port
    serialPort.setBaudRate(QSerialPort::Baud115200);
    serialPort.setDataBits(QSerialPort::Data8);
    serialPort.setParity(QSerialPort::NoParity);
    serialPort.setStopBits(QSerialPort::OneStop);
    serialPort.setFlowControl(QSerialPort::NoFlowControl);

    if (!serialPort.open(QIODevice::ReadWrite)) {
        qDebug() << QObject::tr("Failed to open port %1, error: %2").arg(serialPort.portName()).arg(serialPort.errorString()) << endl;
        return a.exec();
    }

    QObject::connect(&serialPort, &QSerialPort::readyRead, [&]() {
        QByteArray data = serialPort.readAll();
        qDebug() << "Received data:" << data << endl;

        // Send an acknowledgement to the other device
        serialPort.write("ACK\n");
    });

    // Send data to the other device
    QByteArray sendData = "Hello from my device!\n";
    serialPort.write(sendData);

    // Wait for the acknowledgement from the other device
    while(serialPort.waitForReadyRead(1000)) {
        QByteArray data = serialPort.readAll();
        qDebug() << "Received acknowledgement:" << data << endl;
        break;
    }

    return a.exec();
}

(PS: 上面已经解决标题所述的问题了,SH要求多写一点,列举常见应用)
如果单独超时设置不方便也可以定长+超时,下面的程序就是收到一定长度或者超时退出接收,执行处理函数

#include <QCoreApplication>
#include <QSerialPort>
#include <QSerialPortInfo>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QSerialPort serial;
    serial.setPortName("/dev/ttyUSB0");
    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)) {
        qCritical("Failed to open serial port");
        return 1;
    }

    QByteArray ackData;
    while (ackData.size() < 8000) {
        if (serial.waitForReadyRead(8000)) {
            ackData.append(serial.readAll());
        } else {
            qCritical("Timeout waiting for ACK data");
            break;
        }
    }

    // Run next dealing function with the received ACK data
    processAckData(ackData);

    return a.exec();
}

void processAckData(const QByteArray& ackData)
{
    // TODO: Implement your next dealing function here
}

如果发送数据在定时内没有收到回应,则重发数据,如果重发5次都没有回应,则报错,就这样写。

#include <QCoreApplication>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QSerialPort serialPort;
    serialPort.setPortName("/dev/ttyUSB0"); // Replace with the name of your serial port
    serialPort.setBaudRate(QSerialPort::Baud9600);
    serialPort.setDataBits(QSerialPort::Data8);
    serialPort.setParity(QSerialPort::NoParity);
    serialPort.setStopBits(QSerialPort::OneStop);
    serialPort.setFlowControl(QSerialPort::NoFlowControl);

    if (!serialPort.open(QIODevice::ReadWrite)) {
        qDebug() << QObject::tr("Failed to open port %1, error: %2").arg(serialPort.portName()).arg(serialPort.errorString()) << endl;
        return a.exec();
    }

    int ackAttempts = 0;
    while(ackAttempts < 5) {
        // Send data to the other device
        QByteArray sendData = "Hello from my device!\n";
        serialPort.write(sendData);

        // Wait for the acknowledgement from the other device
        while(serialPort.waitForReadyRead(1000)) {
            QByteArray data = serialPort.readAll();
            qDebug() << "Received acknowledgement in hexadecimal format:" << data.toHex(' ') << endl;
            break;
        }

        ackAttempts++;

        if(ackAttempts == 5) {
            qDebug() << "Could not receive acknowledgement after 5 attempts. Breaking loop." << endl;
            break;
        }
    }

    return a.exec();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值