写一段QT6,操作串口收发数据的代码,要求界面显示和串口读取和数据处理是三个线程,界面配置串口,开始读取串口,读取的串口数据交给再处理线程,处理线程将数据转成base64后发送给界面线程
时间: 2024-05-07 17:20:36 浏览: 125
以下是一个基本的QT6串口通信的代码示例,实现了串口数据的读取和发送,并且将读取的数据进行Base64编码后发送给界面线程。
```
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QThread>
#include <QByteArray>
#include <QDebug>
#include <QMutex>
#include <QWaitCondition>
#include <QCoreApplication>
#include <QTextCodec>
#include <QDataStream>
class SerialThread : public QThread
{
Q_OBJECT
public:
explicit SerialThread(QObject *parent = nullptr)
: QThread(parent)
, m_serialPort(nullptr)
, m_mutex(QMutex::Recursive)
, m_waitCond(m_mutex)
{
}
~SerialThread() override
{
if (isRunning()) {
stop();
}
}
void setPortName(const QString &portName)
{
m_portName = portName;
}
void setBaudRate(qint32 baudRate)
{
m_baudRate = baudRate;
}
void start() override
{
QMutexLocker locker(&m_mutex);
m_stop = false;
QThread::start();
}
void stop()
{
{
QMutexLocker locker(&m_mutex);
m_stop = true;
}
m_waitCond.wakeAll();
wait();
}
signals:
void dataReceived(const QByteArray &data);
protected:
void run() override
{
m_serialPort = new QSerialPort(m_portName, this);
m_serialPort->setBaudRate(m_baudRate);
if (!m_serialPort->open(QIODevice::ReadWrite)) {
qDebug() << "Failed to open serial port:" << m_serialPort->errorString();
delete m_serialPort;
m_serialPort = nullptr;
return;
}
while (!m_stop) {
if (m_serialPort->waitForReadyRead(500)) {
QByteArray data = m_serialPort->readAll();
if (!data.isEmpty()) {
emit dataReceived(data.toBase64());
}
}
{
QMutexLocker locker(&m_mutex);
if (m_stop) {
break;
}
m_waitCond.wait(&m_mutex, 500);
}
}
m_serialPort->close();
delete m_serialPort;
m_serialPort = nullptr;
}
private:
QString m_portName;
qint32 m_baudRate;
QSerialPort *m_serialPort;
QMutex m_mutex;
QWaitCondition m_waitCond;
bool m_stop;
};
class DecodeThread : public QThread
{
Q_OBJECT
public:
explicit DecodeThread(QObject *parent = nullptr)
: QThread(parent)
, m_mutex(QMutex::Recursive)
, m_waitCond(m_mutex)
{
}
~DecodeThread() override
{
if (isRunning()) {
stop();
}
}
void addData(const QString &data)
{
QMutexLocker locker(&m_mutex);
m_data.append(data);
}
void start() override
{
QMutexLocker locker(&m_mutex);
m_stop = false;
QThread::start();
}
void stop()
{
{
QMutexLocker locker(&m_mutex);
m_stop = true;
}
m_waitCond.wakeAll();
wait();
}
signals:
void dataDecoded(const QByteArray &data);
protected:
void run() override
{
while (!m_stop) {
QByteArray data;
{
QMutexLocker locker(&m_mutex);
if (!m_data.isEmpty()) {
data = QByteArray::fromBase64(m_data.toUtf8());
m_data.clear();
}
}
if (!data.isEmpty()) {
emit dataDecoded(data);
}
{
QMutexLocker locker(&m_mutex);
if (m_stop) {
break;
}
m_waitCond.wait(&m_mutex, 500);
}
}
}
private:
QString m_data;
QMutex m_mutex;
QWaitCondition m_waitCond;
bool m_stop;
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr)
: QMainWindow(parent)
, m_serialThread(new SerialThread(this))
, m_decodeThread(new DecodeThread(this))
{
m_serialThread->setPortName("COM1");
m_serialThread->setBaudRate(9600);
connect(m_serialThread, &SerialThread::dataReceived,
m_decodeThread, &DecodeThread::addData);
connect(m_decodeThread, &DecodeThread::dataDecoded,
this, &MainWindow::onDataDecoded);
m_serialThread->start();
m_decodeThread->start();
}
~MainWindow() override
{
m_serialThread->stop();
m_decodeThread->stop();
}
private slots:
void onDataDecoded(const QByteArray &data)
{
// handle decoded data
}
private:
SerialThread *m_serialThread;
DecodeThread *m_decodeThread;
};
```
在这个示例中,我们创建了两个线程,`SerialThread` 和 `DecodeThread`,并且将串口读取和数据处理分别放在了这两个线程中。`SerialThread` 负责实际的串口读取操作,并且将读取的数据使用Base64编码后发送给 `DecodeThread`。`DecodeThread` 则负责将Base64编码后的数据解码,并且将解码后的数据发送给主线程。
主线程中创建了两个线程,并且将它们连接起来,然后启动这两个线程。在窗口关闭时,我们调用了 `stop()` 方法来停止这两个线程。
注意,在这个示例中,我们使用了 `QMutex` 和 `QWaitCondition` 来实现了线程之间的同步和等待。这些工具可以帮助我们更安全地使用线程,避免出现数据竞争和死锁等问题。
阅读全文