QT串口读取
QT Serial Port Reading
我正在尝试通过 USB 读取设备插头发送的数据。
首先我通过这个命令读取数据
- sudo stty -F /dev/ttyUSB0 1200 sane parenb evenp cs7 -crtscts
- 猫/dev/ttyUSB0
而数据是这样的
TGPHI_s -0,24 =
MESURES2 BT 4 SUP36 A
PTCOUR2 HPH /
现在我想通过Qt5.3程序读取数据
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;
答案是 ->
"/dev/ttyUSB0"
0
Serial port is open...
Arrived data: 0
Serial port is open...
Arrived data: 0
所以我的程序没有捕获数据...
我的问题是:
- 我是否遗漏了 QSerialPort 设置中的某些内容?
- 如果没有为什么qDebug()没有数据显示
编辑
感谢迈克,我终于可以读取这个 USB 设备了!!!
这是我的最终代码
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();
Qt 中的大多数 IO 函数都是异步的。这意味着 readAll()
不等待数据到达。相反,它 returns 当前可用数据(无需等待即可从设备读取的数据)。目前,你只是在无限循环中调用readAll
(这使得线程,将所有时间都花在这个循环中,无法接收可能已经到达的新数据。。。)
只有当您知道有新数据到达时才需要调用readAll
。这可以通过两种方式完成:
非阻塞异步方式:
使用 readyRead()
信号在设备中有新数据可用时获得通知,而不是永远循环。这是您在 Qt 中应该做的大多数事情,以便能够对可能随时到达的多个事件采取行动。您的代码可以这样重写:
#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
}
阻塞同步方式:
使用waitForReadyRead()
阻塞线程直到新数据到达串口。这使得调用线程在新数据到达此串行端口之前无法执行任何操作。如果这个线程是一个 GUI 线程,这将使应用程序在那段时间内没有响应。仅当您确定这是您想要的时才使用此方法。您的代码可以这样重写:
#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;
}
我正在尝试通过 USB 读取设备插头发送的数据。 首先我通过这个命令读取数据
- sudo stty -F /dev/ttyUSB0 1200 sane parenb evenp cs7 -crtscts
- 猫/dev/ttyUSB0
而数据是这样的
TGPHI_s -0,24 =
MESURES2 BT 4 SUP36 A
PTCOUR2 HPH /
现在我想通过Qt5.3程序读取数据
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;
答案是 ->
"/dev/ttyUSB0"
0
Serial port is open...
Arrived data: 0
Serial port is open...
Arrived data: 0
所以我的程序没有捕获数据... 我的问题是:
- 我是否遗漏了 QSerialPort 设置中的某些内容?
- 如果没有为什么qDebug()没有数据显示
编辑
感谢迈克,我终于可以读取这个 USB 设备了!!! 这是我的最终代码
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();
Qt 中的大多数 IO 函数都是异步的。这意味着 readAll()
不等待数据到达。相反,它 returns 当前可用数据(无需等待即可从设备读取的数据)。目前,你只是在无限循环中调用readAll
(这使得线程,将所有时间都花在这个循环中,无法接收可能已经到达的新数据。。。)
只有当您知道有新数据到达时才需要调用readAll
。这可以通过两种方式完成:
非阻塞异步方式:
使用
readyRead()
信号在设备中有新数据可用时获得通知,而不是永远循环。这是您在 Qt 中应该做的大多数事情,以便能够对可能随时到达的多个事件采取行动。您的代码可以这样重写:#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 }
阻塞同步方式:
使用
waitForReadyRead()
阻塞线程直到新数据到达串口。这使得调用线程在新数据到达此串行端口之前无法执行任何操作。如果这个线程是一个 GUI 线程,这将使应用程序在那段时间内没有响应。仅当您确定这是您想要的时才使用此方法。您的代码可以这样重写:#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; }