QT Serial Port Reading
Most IO functions in Qt are asynchronous. This means that readAll()
does not wait for data to arrive. Instead, it returns currently available data (data that can be read from the device without waiting). Currently, You are just calling readAll
in an endless loop (this makes the thread, spend all its time in this loop, unable to receive the new data that may have arrived. . .)
You need to call readAll
only when you know that new data has arrived. This can be accomplished in two ways:
-
Non-blocking Asynchronous Way:
Use the
readyRead()
signal to get notified when new data is available in the device instead of looping forever. This is how you should do most stuff in Qt, In order to be able to act upon multiple events that may arrive at any time. Your code can be rewritten like this:#include <QtSerialPort> int main(int argc, char* argv[]){ QCoreApplication a(argc, argv); QSerialPort serial; serial.setPortName("ttyUSB0"); if(!serial.setBaudRate(QSerialPort::Baud1200)) qDebug() << serial.errorString(); if(!serial.setDataBits(QSerialPort::Data7)) qDebug() << serial.errorString(); if(!serial.setParity(QSerialPort::EvenParity)) qDebug() << serial.errorString(); if(!serial.setFlowControl(QSerialPort::HardwareControl)) qDebug() << serial.errorString(); if(!serial.setStopBits(QSerialPort::OneStop)) qDebug() << serial.errorString(); if(!serial.open(QIODevice::ReadOnly)) qDebug() << serial.errorString(); QObject::connect(&serial, &QSerialPort::readyRead, [&] { //this is called when readyRead() is emitted qDebug() << "New data available: " << serial.bytesAvailable(); QByteArray datas = serial.readAll(); qDebug() << datas; }); QObject::connect(&serial, static_cast<void(QSerialPort::*)(QSerialPort::SerialPortError)> (&QSerialPort::error), [&](QSerialPort::SerialPortError error) { //this is called when a serial communication error occurs qDebug() << "An error occured: " << error; a.quit(); }); return a.exec(); // ^^^^^^^^ //very important: starts the Qt main event loop //this makes all asynchronous stuff possible }
-
Blocking Synchronous Way:
Use
waitForReadyRead()
to block the thread until new data arrives to the serial port. This makes the calling thread unable to do anything until new data arrives on this serial port. If this thread was a GUI thread, This will make the application unresponsive during that period of time. Use this approach only when you are sure this is what you want. Your code can be rewritten like this:#include <QtSerialPort> int main(int argc, char* argv[]){ QCoreApplication a(argc, argv); QSerialPort serial; serial.setPortName("ttyUSB0"); if(!serial.setBaudRate(QSerialPort::Baud1200)) qDebug() << serial.errorString(); if(!serial.setDataBits(QSerialPort::Data7)) qDebug() << serial.errorString(); if(!serial.setParity(QSerialPort::EvenParity)) qDebug() << serial.errorString(); if(!serial.setFlowControl(QSerialPort::HardwareControl)) qDebug() << serial.errorString(); if(!serial.setStopBits(QSerialPort::OneStop)) qDebug() << serial.errorString(); if(!serial.open(QIODevice::ReadOnly)) qDebug() << serial.errorString(); qDebug() << serial.bytesAvailable(); while(serial.isOpen()) { if(!serial.waitForReadyRead(-1)) //block until new data arrives qDebug() << "error: " << serial.errorString(); else{ qDebug() << "New data available: " << serial.bytesAvailable(); QByteArray datas = serial.readAll(); qDebug() << datas; } } return 0; }
Admin
Updated on June 04, 2022Comments
-
Admin almost 2 years
I am trying to read the data sent by a device plug via usb. First i read the data via this command
- sudo stty -F /dev/ttyUSB0 1200 sane parenb evenp cs7 -crtscts
- cat /dev/ttyUSB0
And the data are like this
TGPHI_s -0,24 = MESURES2 BT 4 SUP36 A PTCOUR2 HPH /
Now i want to read the data via a Qt5.3 program
QSerialPort serial; serial.setPortName("ttyUSB0"); if(!serial.setBaudRate(QSerialPort::Baud1200 , QSerialPort::Input)) qDebug() << serial.errorString(); if(!serial.setDataBits(QSerialPort::Data7)) qDebug() << serial.errorString(); if(!serial.setParity(QSerialPort::EvenParity)) qDebug() << serial.errorString(); if(!serial.setFlowControl(QSerialPort::HardwareControl)) qDebug() << serial.errorString(); if(!serial.setStopBits(QSerialPort::OneStop)) qDebug() << serial.errorString(); if(!serial.open(QIODevice::ReadOnly)) qDebug() << serial.errorString(); qDebug() << serial.bytesAvailable(); while(true) { if (serial.isOpen()) { qDebug() << "Serial port is open..."; QByteArray datas = serial.readAll(); if (datas.size() == 0) { qDebug() << "Arrived data: 0"; } else { for (int i = 0; i < datas.size(); i++){ if (datas.at(i)) { qDebug() << datas[i]; } } } } else { qDebug() << "OPEN ERROR: " << serial.errorString(); } } return 0;
and the answer is ->
"/dev/ttyUSB0" 0 Serial port is open... Arrived data: 0 Serial port is open... Arrived data: 0
So there is no data catch by my program ... My questions are :
- Did i miss something in the setting of the QSerialPort ?
- If no why there is no data display via the qDebug()
EDIT
Thanks to mike i can finaly read this usb device !!! here is my final code
QSerialPort serial; serial.setPortName("ttyUSB0"); if(!serial.setBaudRate(QSerialPort::Baud1200)) qDebug() << serial.errorString(); if(!serial.setDataBits(QSerialPort::Data7)) qDebug() << serial.errorString(); if(!serial.setParity(QSerialPort::EvenParity)) qDebug() << serial.errorString(); if(!serial.setFlowControl(QSerialPort::HardwareControl)) qDebug() << serial.errorString(); if(!serial.setStopBits(QSerialPort::OneStop)) qDebug() << serial.errorString(); if(!serial.open(QIODevice::ReadOnly)) qDebug() << serial.errorString(); QObject::connect(&serial, &QSerialPort::readyRead, [&] { //this is called when readyRead() is emitted //qDebug() << "New data available: " << serial.bytesAvailable(); qDebug() << "New data available: " << serial.bytesAvailable(); QByteArray datas = serial.readAll(); qDebug() << datas; }); QObject::connect(&serial, static_cast<void(QSerialPort::*)(QSerialPort::SerialPortError)> (&QSerialPort::error), [&](QSerialPort::SerialPortError error) { //this is called when a serial communication error occurs qDebug() << "An error occured: " << error; return qApp->quit(); }); if(!serial.open(QIODevice::ReadOnly)) qDebug() << serial.errorString(); return qApp->exec();