忙了两三天了,总算得空记录一下QT串口,文末会有总的工程文件上传,多谢大家捧场。
之前博文写过PyQT,目前我逐渐偏向C++了,但主要代码思想没有变,如下:
第一,在QTdesigner下,建立好UI,如下图:
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));
}
看一下运行效果,
运行后
打开串口,发送指令
主要功能是,按SET+电压值+V
的格式向DSP28335发送命令,如果DSP正确解析命令并调节出相应电压值,则返回V
,经多次测试OK。
logo和自适应窗口大小还没做,界面还比较单调,以后会逐渐完善的
总体上,本工程可实现多个串口多线程通信,但是,目前的工程文件,只实现了基本框架以及基本的串口功能,该功能预留了框架,有些地方还在扩展中,时间关系,以后会逐渐更新。以下是全部工程压缩文件,欢迎大家拍砖哈
https://download.csdn.net/download/ysgjiangsu/10329501