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();