QT C++ 多线程多串口界面设计

忙了两三天了,总算得空记录一下QT串口,文末会有总的工程文件上传,多谢大家捧场。
之前博文写过PyQT,目前我逐渐偏向C++了,但主要代码思想没有变,如下:

第一,在QTdesigner下,建立好UI,如下图:
QT C++ 多线程多串口界面设计_第1张图片
UI细节就不详细说了,具体可以看文末连接的工程文件

第二,新建串口线程类,这里要说明一下,QT本身已有串口类,我这里继承了QThread后,在类内添加串口类成员,代码如下:

#ifndef TASERIALTHREAD_H
#define TASERIALTHREAD_H

#include 
#include 
#include 
#include 

class TA_SerialThread:public QThread
{
public:
    TA_SerialThread();
    ~TA_SerialThread();

public:
    uint8_t portCnt;
    QSerialPort *m_arrSerial;//ptr point to an array,maxium port num is 5

public:
    void SearchPort(void);
    void InitPortName(uint8_t portIndex,const QString &portName);
    void InitPortBaudRate(uint8_t portIndex,qint32 baudRate);
    void InitPortDataBits(uint8_t portIndex,QSerialPort::DataBits dataBits);
    void InitPortParity(uint8_t portIndex,QSerialPort::Parity parity);
    void InitPortStopBits(uint8_t portIndex,QSerialPort::StopBits stopBits);
    void OpenPort(uint8_t portIndex);
    void ClosePort(uint8_t portIndex);
    void SendDataBuf(uint8_t portIndex,const QByteArray &str);
    QByteArray GetDataBuf(uint8_t portIndex);

private slots:
    void run();
};
#endif // TASERIALTHREAD_H

有几处说明,

QSerialPort *m_arrSerial;

指针用于存储多个串口,当串口数组用了

uint8_t portCnt;

用于标记当前串口的总个数
portIndex用于明确对哪个串口操作

第三,新建主窗口类,目的是将ui与底层连接起来,把二者融合在一个类里,类如下:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include "taserialthread.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

public slots:
    void MWOnoffPort(void);
    void MWSendCmd(void);
    void MWReadData(void);
    void MWClearRecv(void);
    void MWRSNumDisplay(void);

private:
    Ui::MainWindow *ui;
    TA_SerialThread *sPortThread;
    volatile uint32_t m_recvNum;
    volatile uint32_t m_sendNum;
};

#endif // MAINWINDOW_H

都是通过私有成员的方式,添加进类MainWindow

第四,信号与槽连接以及细节处理

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_recvNum = 0;
    m_sendNum = 0;
    sPortThread = new TA_SerialThread;
    sPortThread->SearchPort();

    for(uint8_t i = 0;i < sPortThread->portCnt;i++)
        ui->comboBox_SPortName->addItem(sPortThread->m_arrSerial[i].portName());

    //0:1200 1:2400 2:4800 3:9600 4:19200 5:38400 6:57600 7:115200
    ui->comboBox_SPortBaud->setCurrentIndex(3);
    //0:5 1:6 2:7 3:8
    ui->comboBox_SPortDataBit->setCurrentIndex(3);
    //0:no p 2:e p 3:o p 4:s p 5:m p
    ui->comboBox_SPortOEBit->setCurrentIndex(0);
    //0:1 1:2 2:1.5
    ui->comboBox_SPortStopBit->setCurrentIndex(0);

    ui->pushButton_SendCmd->setEnabled(false);
    ui->graphicsView_ComStatus->setStyleSheet("background-color: rgb(255, 0, 0);");
    ui->label_ComStatus->setText(tr("串口状态: 断开"));

    connect(ui->pushButton_OpenCom, SIGNAL(clicked(bool)), this, SLOT(MWOnoffPort()));
    connect(ui->pushButton_SendCmd, SIGNAL(clicked(bool)), this, SLOT(MWSendCmd()));
    connect(ui->pushButton_ClearRecv,SIGNAL(clicked(bool)),this, SLOT(MWClearRecv()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::MWOnoffPort(void)
{
    uint8_t comIndex = ui->comboBox_SPortName->currentIndex();

    if(ui->pushButton_OpenCom->text()==tr("打开串口"))
    {
        sPortThread->InitPortName(comIndex,ui->comboBox_SPortName->currentText());
        sPortThread->InitPortBaudRate(comIndex,ui->comboBox_SPortBaud->currentText().toInt());

        //qDebug()<comboBox_SPortDataBit->currentIndex();
        switch(ui->comboBox_SPortDataBit->currentIndex())
        {
            case 0: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data5); break;//0:5
            case 1: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data6); break;//1:6
            case 2: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data7); break;//2:7
            case 3: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data8); break;//3:8
            default: break;
        }

        switch(ui->comboBox_SPortStopBit->currentIndex())
        {
            case 0:sPortThread->InitPortStopBits(comIndex,QSerialPort::OneStop);break;
            case 1:sPortThread->InitPortStopBits(comIndex,QSerialPort::TwoStop);break;
            case 2:sPortThread->InitPortStopBits(comIndex,QSerialPort::OneAndHalfStop);break;
            default: break;
        }

        switch(ui->comboBox_SPortOEBit->currentIndex())
        {
            case 0:sPortThread->InitPortParity(comIndex,QSerialPort::NoParity);break;
            case 1:sPortThread->InitPortParity(comIndex,QSerialPort::EvenParity);break;
            case 2:sPortThread->InitPortParity(comIndex,QSerialPort::OddParity);break;
            case 3:sPortThread->InitPortParity(comIndex,QSerialPort::SpaceParity);break;
            case 4:sPortThread->InitPortParity(comIndex,QSerialPort::MarkParity);break;
            default: break;
        }
        sPortThread->OpenPort(comIndex);

        connect(&(sPortThread->m_arrSerial[comIndex]), SIGNAL(readyRead()), this, SLOT(MWReadData()));

        //参数设置禁止
        ui->comboBox_SPortName->setEnabled(false);
        ui->comboBox_SPortBaud->setEnabled(false);
        ui->comboBox_SPortDataBit->setEnabled(false);
        ui->comboBox_SPortOEBit->setEnabled(false);
        ui->comboBox_SPortStopBit->setEnabled(false);
        ui->pushButton_OpenCom->setText(tr("关闭串口"));
        //发送设置使能
        ui->pushButton_SendCmd->setEnabled(true);
        ui->graphicsView_ComStatus->setStyleSheet("background-color: rgb(0, 255, 0);");
        ui->label_ComStatus->setText(tr("串口状态: 连接"));
    }
    else
    {
        sPortThread->ClosePort(comIndex);
        //参数设置使能
        ui->comboBox_SPortName->setEnabled(true);
        ui->comboBox_SPortBaud->setEnabled(true);
        ui->comboBox_SPortDataBit->setEnabled(true);
        ui->comboBox_SPortOEBit->setEnabled(true);
        ui->comboBox_SPortStopBit->setEnabled(true);
        ui->pushButton_OpenCom->setText(tr("打开串口"));
        //发送设置禁止
        ui->pushButton_SendCmd->setEnabled(false);
        ui->graphicsView_ComStatus->setStyleSheet("background-color: rgb(255, 0, 0);");
        ui->label_ComStatus->setText(tr("串口状态: 断开"));
    }
}

void MainWindow::MWSendCmd(void)
{
   sPortThread->SendDataBuf(ui->comboBox_SPortName->currentIndex(),ui->textEdit->toPlainText().toLatin1());
   m_sendNum +=  (ui->textEdit->toPlainText().toLatin1()).length();
   MWRSNumDisplay();
}

void MainWindow::MWReadData(void)
{
    QByteArray buf;

    buf = sPortThread->GetDataBuf(ui->comboBox_SPortName->currentIndex());

    if(!buf.isEmpty())
    {
        QString str = ui->textBrowser->toPlainText();
        str += tr(buf);
        ui->textBrowser->clear();
        ui->textBrowser->append(str);
        m_recvNum += tr(buf).length();
        MWRSNumDisplay();
    }

    buf.clear();
}

void MainWindow::MWClearRecv(void)
{
    ui->textBrowser->clear();
    m_recvNum = 0;
    m_sendNum = 0;
    MWRSNumDisplay();
}

void MainWindow::MWRSNumDisplay(void)
{
    ui->label_RecvNum->setText(tr("已接收:") + QString::number(m_recvNum,10));
    ui->label_SendNum->setText(tr("已发送:") + QString::number(m_sendNum,10));
}

看一下运行效果,
运行后
QT C++ 多线程多串口界面设计_第2张图片
打开串口,发送指令
QT C++ 多线程多串口界面设计_第3张图片
主要功能是,按SET+电压值+V的格式向DSP28335发送命令,如果DSP正确解析命令并调节出相应电压值,则返回V,经多次测试OK。

logo和自适应窗口大小还没做,界面还比较单调,以后会逐渐完善的

总体上,本工程可实现多个串口多线程通信,但是,目前的工程文件,只实现了基本框架以及基本的串口功能,该功能预留了框架,有些地方还在扩展中,时间关系,以后会逐渐更新。以下是全部工程压缩文件,欢迎大家拍砖哈
https://download.csdn.net/download/ysgjiangsu/10329501

你可能感兴趣的:(Linux+QT)