使用QT5实现串口数据接收和存储的多线程技巧 (qt5线程接收串口数据库)
QT5是一款跨平台的GUI应用程序开发工具,它提供了高效、易用、可扩展的程序开发框架。在业界得到了广泛的应用和认可,常常被用于工业控制、嵌入式系统、图形化应用等领域。今天我们就来讲一讲如何使用QT5来实现串口数据接收和存储的多线程技巧。
1、串口的通讯原理
串口通讯是指通过串行线路进行传输的一种通讯方式,通常被用于传输实时数据、控制信号等。串口通讯需要两个设备之间建立好物理连接,并在数据传输过程中采用同一方式的信号协议进行数据交换。一般情况下,串口的通讯协议主要包括数据位、波特率、停止位、校验位、流控制等内容。
2、QT5中的串口通讯
QT5提供了一个 QSerialPort 类,可用于串口通讯。这个类继承自 QIODevice 类,因此,QT5可以通过它方便地读写串口数据。使用 QSerialPort 的步骤如下:
(1)、创建 QSerialPort 对象
QSerialPort serialPort;
(2)、设置串口参数
serialPort.setPortName(“COM1”); // 设置串口号
serialPort.setBaudRate(QSerialPort::Baud9600);// 设置波特率
serialPort.setDataBits(QSerialPort::Data8); // 设置数据位
serialPort.setParity(QSerialPort::NoParity); // 设置校验位
serialPort.setStopBits(QSerialPort::OneStop); // 设置停止位
(3)、打开串口
serialPort.open(QIODevice::ReadOnly);
(4)、读/写串口数据
serialPort.read(data, size); // 读取数据
serialPort.write(data, size); // 发送数据
(5)、关闭串口
serialPort.close();
3、多线程技巧的应用
串口通讯往往需要长时间稳定地运行,且数据量大。但是,如果不采用多线程技巧,将会导致程序的阻塞,从而使得操作系统无法响应要求。为了解决这个问题,我们需要把串口通讯放在一个单独的线程里运行。
建立一个新的线程类 SerialThread,我们可以继承 QThread 类,然后实现 run 函数。在这个函数里,我们可以把串口通讯代码放在一个死循环里,直到用户终止或线程崩溃为止。具体的代码如下:
class SerialThread : public QThread
{
Q_OBJECT
public:
SerialThread(QObject *parent = nullptr);
~SerialThread();
void run(); // 重载 run 函数
private:
QSerialPort serialPort;
bool m_quit; // 停止线程的标志
};
SerialThread::SerialThread(QObject *parent) :
QThread(parent), m_quit(false)
{
}
SerialThread::~SerialThread()
{
if(serialPort.isOpen()) {
serialPort.close();
}
}
void SerialThread::run()
{
while(!m_quit) {
if(serialPort.wtForReadyRead(1000)) { // 等待数据
QByteArray data = serialPort.readAll(); // 读取数据
if(!data.isEmpty()) { // 保存数据到文件
QFile outFile(“data.txt”);
outFile.open(QIODevice::Append | QIODevice::Text);
QTextStream out(&outFile);
out
outFile.close();
}
}
}
}
在这个代码中,我们启动了一个死循环,当串口有数据可读时,它会把数据全部读取并保存到一个文本文件中。当用户选择停止线程时,将设置 m_quit 标志位为 true,从而结束循环。
4、线程管理的方法
在应用程序中,线程的数量可能非常多,为了方便管理,我们需要使用 QT5 中的线程池, 线程池中的线程可以按照指定的规则工作。常用的管理方法有:
(1)、QThreadPool 类
QThreadPool 类提供了管理线程池的接口和方法,主要包括 start 和 stop 函数。通过 QThreadPool,我们可以轻松地管理线程池中的线程。例如,创建一个线程池,添加一个新线程,删除一个线程的代码如下:
QThreadPool *pool = QThreadPool::globalInstance();
pool->setMaxThreadCount(4); // 设置线程池中更大线程数
SerialThread *thread = new SerialThread();
pool->start(thread); // 添加新线程
pool->wtForDone(); // 等待所有线程执行完后返回
(2)、等待线程执行完毕
线程在执行过程中,我们有时需要等待某个线程完成后才能进行下一步操作,此时可以通过调用线程的 wt 函数实现等待。例如:
SerialThread *thread = new SerialThread();
thread->start(); // 启动线程
thread->wt(); // 等待线程执行完毕
(3)、线程常用信号槽
QT5 提供了许多用于线程通信的信号和槽,例如 finished、started、terminated 等。我们可以通过这些信号和槽来实现让线程间进行通信,共享数据等。例如:
SerialThread *thread = new SerialThread();
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start(); // 启动线程
在这个例子中,我们使用了 finished 信号,当线程执行结束时会发出这个信号,我们在这个信号对应的槽里进行善后操作,例如线程的删除。
综述
通过 QT5 实现串口数据接收和存储的多线程技巧,可以有效地保证系统的稳定性和高效性,有效地应用于工业控制、嵌入式系统、图形化应用等领域。了解了这个技巧之后,我们可以更好地使用 QT5 进行软件开发。