QT C++ 多執行緒多串列埠介面設計
阿新 • • 發佈:2018-11-29
忙了兩三天了,總算得空記錄一下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