一、前言
串口通信作为嵌入式开发和硬件调试的重要工具,在工业控制、物联网等领域广泛应用。本文将手把手教你使用QT框架实现一个跨平台的串口调试助手,支持Windows/Linux/macOS系统。
使用版本为Qt 6以上版本
二、效果
三、界面
控件
四、项目引用
在 .pro 文件中添加模块依赖:
QT += serialport
五、头文件声明
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QSerialPort>
#include <QSerialPortInfo>QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_btnRefreshSerialPort_clicked();void initUiData();void on_btnOpen_clicked();void initSerialPort(QSerialPort *serialPort,QString name,int baudRate,int dataBit,QString parity,int stopBit);void on_btnSend_clicked();void receiveData();void controlEnable(bool isEnable);void on_btnClear_clicked();void on_btnSendClear_clicked();private:Ui::MainWindow *ui;QList<QString> BaudRateList;QList<int> DataBitList;QList<QString> ParityList;QList<int> StopBitList;QSerialPort serialPort;
};
#endif // MAINWINDOW_H
六、Cpp代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);initUiData();
}MainWindow::~MainWindow()
{delete ui;
}//刷新串口
void MainWindow::on_btnRefreshSerialPort_clicked()
{ui->cboSerialPort->clear();QList<QSerialPortInfo> serialPostList = QSerialPortInfo::availablePorts();foreach(const QSerialPortInfo &info,serialPostList){ui->cboSerialPort->addItem(info.portName());//添加串口名称}
}void MainWindow::initUiData()
{on_btnRefreshSerialPort_clicked();BaudRateList.append("1200");BaudRateList.append("2400");BaudRateList.append("4800");BaudRateList.append("9600");BaudRateList.append("19200");BaudRateList.append("38400");BaudRateList.append("57600");BaudRateList.append("115200");DataBitList.append(5);DataBitList.append(6);DataBitList.append(7);DataBitList.append(8);ParityList.append("无");ParityList.append("奇校验");ParityList.append("偶校验");StopBitList.append(1);StopBitList.append(2);foreach (auto item, BaudRateList) {ui->cboBaudRate->addItem(item);}ui->cboBaudRate->setCurrentText("9600");foreach (auto item, DataBitList) {ui->cboDataBits->addItem(QString::number(item));}ui->cboDataBits->setCurrentText("8");foreach (auto item, ParityList) {ui->cboParityBit->addItem(item);}ui->cboParityBit->setCurrentText("无");foreach (auto item, StopBitList) {ui->cboStopBit->addItem(QString::number(item));}ui->cboStopBit->setCurrentText("1");
}//打开串口
void MainWindow::on_btnOpen_clicked()
{if(serialPort.isOpen()){//关闭串口serialPort.close();ui->lbStatus->setText("未打开");ui->btnOpen->setText("打开串口");controlEnable(true);disconnect(&serialPort,&QSerialPort::readyRead,this,&MainWindow::receiveData);}else{//打开串口auto name = ui->cboSerialPort->currentText();int baudRate = ui->cboBaudRate->currentText().toInt();int dataBit = ui->cboDataBits->currentText().toInt();auto parity = ui->cboParityBit->currentText();int stopBit = ui->cboStopBit->currentText().toInt();initSerialPort(&serialPort,name,baudRate,dataBit,parity,stopBit);bool isOk = serialPort.open(QIODevice::ReadWrite);if(isOk){//接收数据connect(&serialPort,&QSerialPort::readyRead,this,&MainWindow::receiveData);ui->lbStatus->setText("打开成功");ui->btnOpen->setText("关闭串口");controlEnable(false);}else{ui->lbStatus->setText("打开失败");}}
}void MainWindow::initSerialPort(QSerialPort *serialPort,QString name,int baudRate,int dataBit,QString parity,int stopBit)
{serialPort->setPortName(name);serialPort->setBaudRate(baudRate);switch(dataBit){case 5:serialPort->setDataBits(QSerialPort::Data5);break;case 6:serialPort->setDataBits(QSerialPort::Data6);break;case 7:serialPort->setDataBits(QSerialPort::Data7);break;case 8:serialPort->setDataBits(QSerialPort::Data8);break;}if(parity == "无"){serialPort->setParity(QSerialPort::NoParity);}else if(parity == "奇校验"){serialPort->setParity(QSerialPort::OddParity);}else if(parity == "偶校验"){serialPort->setParity(QSerialPort::EvenParity);}if(stopBit == 1){serialPort->setStopBits(QSerialPort::OneStop);}else if(stopBit == 1){serialPort->setStopBits(QSerialPort::TwoStop);}serialPort->setFlowControl(QSerialPort::NoFlowControl); // 设置流控
}//发送 按钮
void MainWindow::on_btnSend_clicked()
{if(serialPort.isOpen() == true){auto data = ui->txtInputData->toPlainText();if(data.length() > 0){if(ui->chkAddEndMark->checkState() == Qt::Checked){data += "\r\n";}//将字符串转为QByteArrayif(ui->chkHexSend->checkState() == Qt::Checked){//16进制发送QByteArray byteArray = QByteArray::fromHex(data.toUtf8());serialPort.write(byteArray);}else{serialPort.write(data.toUtf8());}ui->textBrowser->append("<font color='green'>发送:"+data.toUtf8());}else{QMessageBox::information(this,"系统提示","发送内容不能为空!");}}else{QMessageBox::information(this,"系统提示","串口未打开,请先打开串口!");}
}void MainWindow::receiveData()
{QByteArray receiveData = serialPort.readAll();if(ui->chkHexReceive->checkState() == Qt::Checked){QString hexData = receiveData.toHex(' '); // 将字节数组转换为16进制字符串,每个字节之间有空格分隔ui->textBrowser->append("<font color='blue'>接收:"+hexData);}else{ui->textBrowser->append("<font color='blue'>接收:"+QString(receiveData));}
}void MainWindow::controlEnable(bool isEnable)
{ui->cboSerialPort->setEnabled(isEnable);ui->cboBaudRate->setEnabled(isEnable);ui->cboDataBits->setEnabled(isEnable);ui->cboParityBit->setEnabled(isEnable);ui->cboStopBit->setEnabled(isEnable);
}void MainWindow::on_btnClear_clicked()
{ui->textBrowser->clear();
}void MainWindow::on_btnSendClear_clicked()
{ui->txtInputData->clear();
}