我被迫在 Qt 中编写一些代码,让传感器与现有的 Qt 代码集成。否则,我已经使用 pyserial 库用非常简单的 Python 代码测试了读取的传感器数据,它就像一个魅力。不幸的是,我不由自主地陷入了Qt框架这个复杂的泥潭。
硬件:传感器通过 USB 转串口适配器插入 Raspberry Pi 4 上的 USB 端口。
传感器配置为每 1 秒输出一行 RS-232 数据,作为以“\r”(CR,ASCII 13)而不是“\n”(LF,ASCII 10)结尾的 ASCII 字符。
这是我的代码:
#include <QCoreApplication>
#include <QThread>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/qserialportinfo.h>
#include <QList>
#include <QString>
#include <stdio.h>
#include <iostream>
#include <QtCore/QDataStream>
static QString sensor = "";
static QList<QSerialPortInfo> portList;
static QSerialPortInfo sensorport;
static QSerialPort s_sensor;
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
portList = QSerialPortInfo::availablePorts();
int size = portList.size();
const auto portnames = portList[1];
std::cout << "Number of ports: " << size << "\n";
for(int i=0;i<size;i++)
{
std::cout << portList[i].portName().toStdString() << " " << portList[i].description().toStdString() << "\n";
if(portList[i].portName().toStdString()=="ttyUSB0"&&portList[i].description().toStdString()=="USB-Serial Controller D")
{
sensor.append(portList[i].portName());
sensorport = portList[i];
}
}
std::cout << sensor.toStdString() << "\n";
std::cout << sensorport.manufacturer().toStdString() << "\n";
s_sensor.setPort(sensorport);
std::cout << s_sensor.open(QIODevice::ReadOnly) << "\n";
std::cout << s_sensor.portName().toStdString() << "\n";
std::cout << s_sensor.parity() << "\n";
std::cout << s_sensor.baudRate() << "\n";
std::cout << s_sensor.dataBits() << "\n";
std::cout << s_sensor.stopBits() << "\n";
std::cout << s_sensor.isOpen() << "\n";
//std::cout << s_sensor.canReadLine() << "\n";
//char buf[1024];
//QString buff;
static QByteArray byteArray;
while(s_sensor.isOpen())
{
//QByteArray byteArray;
if(s_sensor.waitForReadyRead())
{
byteArray += s_sensor.readAll();
}
if(QString(byteArray).contains('\r'))
{
QString data = QString(byteArray);//.remove("*");
byteArray.clear();
std::cout << "End of line\n";
std::cout << data.toStdString() << "\n";
}
else
{
//std::cout << "None\n";
}
// if(s_sensor.waitForReadyRead() && s_sensor.bytesAvailable()>=18)
// {
// //std::string ll = s_sensor.readAll().toStdString();
// //std::cout << ll << "\n";
// qint64 len = s_sensor.readLine(buf,1024);
// //QString bb = s_sensor.readAll();
// std::cout << "Num of bytes: " << len << "\n";
// //std::cout << "Num of bytes: " << sizeof(bb) << "\n";
// std::cout << buf << "\n";
// //std::cout << bb.toStdString() << "\n";
// std::cout << "inner Yes" << "\n";
// //break;
// }
//buff = buf;
//std::cout << buff.toStdString() << "\n";
//std::cout << "outer Yes" << "\n";
//qint64 windline = s_sensor.readLine(buf, sizeof(buf));
}
//std::cout << buff.toStdString() << "\n";
return app.exec();
}
该代码显示了许多连续试验的层,如许多不同的注释代码行所示。
当前的代码不会运行。项目构建完成后,Application Output 窗口将永远显示“Starting (...) ...”。这是添加这些的结果:
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv)
return app.exec();
}
添加这些行是为了消除一个奇怪的警告“QSocketNotifier:只能用于以 QThread 开头的线程”。在网上广泛搜索后,我在 SO 上找到了一个答案,说包括 QCoreApplication 来创建事件循环。好吧,添加这些行当然消除了奇怪的警告,但现在我的程序甚至没有启动。
在上述步骤之前,我只有以下内容:
int main()
{
//QCoreApplication app(argc, argv)
//return app.exec();
}
我一直收到奇怪的警告,但我一直忽略它。但另一方面,我的程序运行成功。
但是,在我得到任何输出之前仍然有很长的延迟。构建后的典型等待时间约为 2-3 分钟!
而使用 pyserial 的简单 Python 代码,我在编译后立即得到输出,并且每一行输出都与传感器的 1 秒输出间隔完美同步。这是理想的工作方式。
readLine()我尝试了和的所有组合readAll()。没有指定行尾字符的选项。默认值为“\n”。我终于找到了两种读取每一行数据的替代方法。您可以看到上述两种方式的代码。第一种方法是我不断添加新的传入字符byteArray并检查 '\r' 字符。第二种方法是我指定一行数据的字节大小并读取它。
我不知道我是否在这里做一些根本错误的事情,导致执行延迟很长。在最初的 3 分钟延迟之后,一大堆数据被吐出,然后它继续吐出数据,但没有以任何方式与 1 秒的间隔同步。