1. 程式人生 > >QT C++ 多執行緒多串列埠介面設計

QT C++ 多執行緒多串列埠介面設計

忙了兩三天了,總算得空記錄一下QT串列埠,文末會有總的工程檔案上傳,多謝大家捧場。
之前博文寫過PyQT,目前我逐漸偏向C++了,但主要程式碼思想沒有變,如下:

第一,在QTdesigner下,建立好UI,如下圖(右下角是我自己的小公司,留個爪印哈):
這裡寫圖片描述
UI細節就不詳細說了,具體可以看文末連線的工程檔案

第二,新建串列埠執行緒類,這裡要說明一下,QT本身已有串列埠類,我這裡繼承了QThread後,在類內新增串列埠類成員,程式碼如下:

#ifndef TASERIALTHREAD_H
#define TASERIALTHREAD_H

#include <QThread>
#include <QtSerialPort> #include <QSerialPortInfo> #include <QString> 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 <QMainWindow>
#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()<<ui->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));
}

看一下執行效果,
執行後
這裡寫圖片描述
開啟串列埠,傳送指令
這裡寫圖片描述
主要功能是,按SET+電壓值+V的格式向DSP28335傳送命令,如果DSP正確解析命令並調節出相應電壓值,則返回V,經多次測試OK。

logo和自適應視窗大小還沒做,介面還比較單調,以後會逐漸完善的

總體上,本工程可實現多個串列埠多執行緒通訊,但是,目前的工程檔案,只實現了基本框架以及基本的串列埠功能,該功能預留了框架,有些地方還在擴充套件中,時間關係,以後會逐漸更新。以下是全部工程壓縮檔案,歡迎大家拍磚哈
https://download.csdn.net/download/ysgjiangsu/10329501