200行C++代码写一个QT串口助手

前言

今天分享一个用QT写的串口助手,关键代码会直接在文章的对应位置贴出,完整的工程文件(用的VS 2019)可以进入我的主页免费下载,也可以关注我的公众号“折途想要敲代码” 回复关键词“qt串口助手”免费获取。       

如果是使用QTCreator的小伙伴在项目配置完毕后可以通过复制我提供的工程文件中的.cpp和.h文件来达到同样的效果。

要配置的就是在配置文件中加上串口对应的部分。

使用VS的需要再拓展插件中找到模块管理再加上串口的模块。

需要包含以下头文件。

#include <QtWidgets/QMainWindow>
#include <QPlainTextEdit>
#include <QPushButton>
#include <QComboBox>
#include <QLabel>
#include <QTimer>
#include <QMessageBox>

#include <QSerialPortInfo>
#include <QSerialPort>

#include <qdebug.h>
#include <qvector.h>

布局

写一个应用最重要的就是外观,也就是前端,因为用户是看不见你程序的逻辑的,因此我们首先需要做的就是先把串口助手的外观设计好。

说QT简单的一个很重要的因素就是QT自带一个图形化界面设计(QTDesign),不得不说使用图形化界面去设计界面确实又快又好。不过我个人不喜欢,因为“折途想要敲代码”。

从零开始写一个串口助手还是挺困难的,因此界面我参考的b站江科大自化协提供的串口助手。 

从上图可以知道我们需要往串口助手里添加的组件就四种:两个可编辑内容展示内容的容器,5个按钮,7个用来配置串口通信的多选项以及对应描述功能的文字标签。

发送区和接收区的组件我们选用QPlainTextEdit

按钮使用QPushButton

多选项使用QComboBox

文字标签自然使用的是QLabel

有了布局的信息之后只需要将对应组件创建之后修改大小以及摆放位置即可。

接收区

接收区是接收串口通信传来的数据的,因此我们可以直接设为只读模式。

接收区还配一个按钮“清空接收区”,我们搭配一个信号槽,按下后直接调用QPlainTextEdit自带的clear函数来清空即可。

//接收区初始化
void Serial::ReceiveAeraInit(QWidget* parent) {
    receiveAera = new QPlainTextEdit(parent);
    receiveAera->setFixedSize(800,400);
    receiveAera->move(30,20);
    receiveAera->setReadOnly(true);     //接收区改为只读

    QPushButton* clearReceive = new QPushButton(QString::fromLocal8Bit("清空接收区"),parent);
    clearReceive->setFixedSize(150,50);
    clearReceive->move(680,430);
    //为清空接收区设置信号槽
    QObject::connect(clearReceive, &QPushButton::clicked, [&]() {
        receiveAera->clear();
        });
}

串口设置

我们使用QComboBox多选项组件来配置串口的设置。

 需要配置的是串口号,这个不是固定的,是根据用户连接到电脑的串口来决定的,因此需要动态地获取,我把这一块放在了定时器里,每1000ms扫描一次更新串口号选项。

我们使用QT自带的QSerialPortInfo来获取串口号,把可用的串口号取出,和之前串口号选项来作比较,如果可用的串口出现变化了再更新,如果一直更新的话后面插入的串口会选择不到。

如果获取不到可用串口的话就检查串口是否正确连接,并且检查是否安装了对应的驱动,如果电脑的设备管理器能够看到串口的话,这里也是可以获取的到的。

//刷新可用串口
void Serial::RefreshPort(void) {
    QVector<QString>temp;
    //获取当前可用串口号
    for (const QSerialPortInfo& info : QSerialPortInfo::availablePorts()) {
        temp.push_back(info.portName());
    }
    //排序现有的串口号,用于比较和原有的差距
    qSort(temp.begin(), temp.end());
    if (temp != this->ports) {  //如果可用串口号有变化
        this->portNumber->clear();  //清除原有列表
        this->ports = temp;         //更新串口列表
        for (auto& a : ports) {     //更新新串口
            this->portNumber->addItem(a);
        }
    }
}

接下来是其他配置选项,其他配置都是固定选型,因此我们需要手动添加上去。

因为我主要是用来和stm32来使用的,所以选项是什么我需要参考stm32串口相关代码以及qt串口类支持的参数。

第一个是波特率。下图是QT提供的波特率,以及stm32关于波特率的参数注释。

 综上,我决定给波特率三个选项,4800,9600,19200。

第二个是数据位。

QT支持5~8的数据位长度,而stm32支持8和9位,也就是没得选,只能是8位数据长度,这里可以写死也可以取消数据位长度的配置,不过为了后续功能的拓展,还是加上了数据位长度的多选项部分,只不过目前只有一个选项没得选。

第三个是停止位,qt支持1,1.5,2一共三种选项,stm32多一个0.5,因此我们使用它们的交集,也就是1,1.5,2。

最后一个是校验位,我们可以选择无校验,奇校验,偶校验。

另外两个是接收和发送的格式,可选HEX和文本。

//串口设置初始化
void Serial::SetupInit(QWidget* parent) {
    this->portNumber = new QComboBox(parent);
    this->baudRate = new QComboBox(parent);
    this->dataSize = new QComboBox(parent);
    this->stopSize = new QComboBox(parent);
    this->check = new QComboBox(parent);
    this->receiveMode = new QComboBox(parent);
    this->sendMode = new QComboBox(parent);

    this->baudRate->addItem("4800");
    this->baudRate->addItem("9600");
    this->baudRate->addItem("19200");
    this->dataSize->addItem("8");
    this->stopSize->addItem("1");
    this->stopSize->addItem("1.5");
    this->stopSize->addItem("2");
    this->check->addItem(QString::fromLocal8Bit("无"));
    this->check->addItem(QString::fromLocal8Bit("奇校验"));
    this->check->addItem(QString::fromLocal8Bit("偶校验"));
    this->receiveMode->addItem(QString::fromLocal8Bit("HEX"));
    this->receiveMode->addItem(QString::fromLocal8Bit("文本"));
    this->sendMode->addItem(QString::fromLocal8Bit("HEX"));
    this->sendMode->addItem(QString::fromLocal8Bit("文本"));

    QLabel* portLabel = new QLabel(QString::fromLocal8Bit("串口号"), parent);
    QLabel* baudLabel = new QLabel(QString::fromLocal8Bit("波特率"),parent);
    QLabel* dataLabel = new QLabel(QString::fromLocal8Bit("数据位"),parent);
    QLabel* stopLabel = new QLabel(QString::fromLocal8Bit("停止位"),parent);
    QLabel* checkLabel = new QLabel(QString::fromLocal8Bit("校验位"),parent);
    QLabel* receiveModeLabel = new QLabel(QString::fromLocal8Bit("接收格式"),parent);
    QLabel* sendModeLabel = new QLabel(QString::fromLocal8Bit("发送格式"),parent);

    QVector<QComboBox*>setups;
    setups.push_back(portNumber);
    setups.push_back(baudRate);
    setups.push_back(dataSize);
    setups.push_back(stopSize);
    setups.push_back(check);
    setups.push_back(receiveMode);
    setups.push_back(sendMode);

    QVector<QLabel*>labels;
    labels.push_back(portLabel);
    labels.push_back(baudLabel);
    labels.push_back(dataLabel);
    labels.push_back(stopLabel);
    labels.push_back(checkLabel);
    labels.push_back(receiveModeLabel);
    labels.push_back(sendModeLabel);

    for (int i = 0; i < setups.size(); ++i) {
        setups[i]->setFixedSize(200, 50);
        setups[i]->move(850, 20 + i * 80);
        labels[i]->move(1080,25+i*80);
    }

}

串口核心代码

串口连接和断开我们分别需要两个按钮,江科大用的是同一个按钮,不过我用两个(不是做不到那样的效果,而是我觉得两个按钮表示两种功能比较合适)。

布局完之后就设置信号槽,也就是点击按钮之后的逻辑了。

首先一开始没有连接串口,所以先把断开连接的按钮失效,也就是点不了,并且无法发送数据,因此在发送区的发送按钮也需要失效。

在点击串口连接的按钮之后,判断是否有串口号,而且也只需要判断是否有串口号即可,因为其他配置都是肯定会有并且是合法的。

没有串口号的话那就没有任何反应。

如果有串口号的话就使串口连接的按钮失效,使断开连接按钮和发送区的发送按钮生效。

//串口连接
void Serial::BeginUSART(QWidget* parent) {
    startUSART = new QPushButton(QString::fromLocal8Bit("串口连接"),parent);
    endUSART = new QPushButton(QString::fromLocal8Bit("断开连接"),parent);
    endUSART->setFixedSize(150, 50);
    endUSART->move(1000, 600);
    startUSART->setFixedSize(150, 50);
    startUSART->move(850,600);
    endUSART->setDisabled(true);        //一开始没有连接串口,因此关闭按钮初始化为无效
    //为关闭连接按钮配置信号槽
    QObject::connect(endUSART, &QPushButton::clicked, [&]() {
        endUSART->setDisabled(true);        //使关闭连接按钮失效
        startUSART->setDisabled(false);     //使连接按钮生效
        sendButton->setDisabled(true);      //使发送按钮失效
        serialPort->close();                //断开串口连接
        });
    //为连接按钮配置信号槽
    QObject::connect(startUSART, &QPushButton::clicked, [&]() {
        QString port = portNumber->currentText();
        QString baud = baudRate->currentText();
        QString data = dataSize->currentText();
        QString stop = stopSize->currentText();
        QString ch = check->currentText();
        QString receive = receiveMode->currentText();
        QString send = sendMode->currentText();
        if (port != "") {       //当串口号不为空,即有效时
            endUSART->setDisabled(false);   //使关闭连接按钮生效
            sendButton->setDisabled(false); //使发送按钮生效
            startUSART->setDisabled(true);  //使连接按钮失效
            USART(port,baud,data,stop,ch);  //连接串口
        }
        });
}

接下来开始串口连接的逻辑。

因为比较多,写在lambda的话可读性比较差,因此我单开了一个函数。

在确认串口号有效之后,把配置选项的值传送进串口连接函数,其实不传参数,在函数里直接获取也是可以的,因为多选项的组件属于成员变量,是可以获取到的。

在串口连接函数的开始需要做的就是把选项值换成qt串口类支持的枚举类型,这里我用的if else语句,使用switch也是可以的。

转换完成之后对串口类进行配置然后连接即可。

接下来就是为串口配置信号槽,一旦有数据传来,我们就需要读取数据,并且通过选择的接收模式来对数据进行加工,如果是选了“HEX”,那么就把数据转换为16进制,如果选了“文本”,那么就转换为QString类型。

数据加工完毕之后加入接收区即可。

//串口通信核心
void Serial::USART(QString port, QString baud, QString data,QString stop,QString check) {
    QSerialPort::BaudRate Baud;     //波特率
    QSerialPort::DataBits Data;     //数据位
    QSerialPort::StopBits Stop;     //停止位
    QSerialPort::Parity Check;      //校验位

    if (baud == "4800")  Baud = QSerialPort::Baud4800;
    else if (baud == "9600") Baud = QSerialPort::Baud9600;
    else if (baud == "19200")  Baud = QSerialPort::Baud19200;
    
    if (data == "8") Data = QSerialPort::Data8;

    if (stop == "1") Stop = QSerialPort::OneStop;
    else if (stop == "1.5")Stop = QSerialPort::OneAndHalfStop;
    else if (stop == "2") Stop = QSerialPort::TwoStop;

    if (check == QString::fromLocal8Bit("无")) Check = QSerialPort::NoParity;
    else if (check == QString::fromLocal8Bit("奇校验")) Check = QSerialPort::OddParity;
    else if (check == QString::fromLocal8Bit("偶校验")) Check = QSerialPort::EvenParity;

    serialPort = new QSerialPort(this);
    //为串口设置配置
    serialPort->setBaudRate(Baud);
    serialPort->setPortName(port);
    serialPort->setDataBits(Data);
    serialPort->setParity(Check);
    serialPort->setStopBits(Stop);
    //打开串口
    if (serialPort->open(QSerialPort::ReadWrite)) {
        //配置信号槽,一旦收到数据则开始读取
        QObject::connect(serialPort, &QSerialPort::readyRead, [&]() {
            auto data = serialPort->readAll();
            if (receiveMode->currentText() == "HEX") {      //字节模式
                QString hex = data.toHex(' ');
                receiveAera->appendPlainText(hex);
            }
            else {                                          //文本模式
                QString str = QString(data);
                receiveAera->appendPlainText(str);
            }
            });
    }else {
        QMessageBox::critical(this, QString::fromLocal8Bit("串口打开失败"), QString::fromLocal8Bit("请确认串口是否正确连接"));
    }
}

发送区

最后剩个发送区,跟接收区类似,只不过多了一个发送的按钮。

发送按钮也需要配置信号槽。

当按下发送按钮的时候,我们就获取当前发送区中的数据,如果是发送格式选择了“HEX”,那我们就需要把发送区的数据按照两个数字一组的形式转换为16进制,完成的逻辑可以参考下面的代码。

如果选择的是“文本”,那么就直接把数据转成utf-8的数据格式即可。

转换完成之后就直接对串口类进行写操作就行了。

//发送区初始化
void Serial::SendAeraInit(QWidget* parent) {
    sendAera = new QPlainTextEdit(parent);
    sendAera->setFixedSize(800,100);
    sendAera->move(30,500);

    QPushButton* clearSend = new QPushButton(QString::fromLocal8Bit("清空发送区"), parent);
    clearSend->setFixedSize(150, 50);
    clearSend->move(680, 630);
    QObject::connect(clearSend, &QPushButton::clicked, [&]() {
        sendAera->clear();
        });

    sendButton = new QPushButton(QString::fromLocal8Bit("发送"), parent);
    sendButton->setFixedSize(150, 50);
    sendButton->move(500, 630);
    sendButton->setDisabled(true);
    QObject::connect(sendButton, &QPushButton::clicked, [&]() {
        QString data = sendAera->toPlainText();
        if (sendMode->currentText() == "HEX") {
            QByteArray arr;
            for (int i = 0; i < data.size(); i++){
                if (data[i] == ' ') continue;
                int num = data.mid(i, 2).toUInt(nullptr, 16);       //将数据转为16进制
                i++;
                arr.append(num);
            }
            serialPort->write(arr);
        }else {
            serialPort->write(data.toLocal8Bit().data());           //转为utf-8格式字符串写入
        }
        });
}

.cpp完整代码&.h完整代码

#include "Serial.h"

//串口通信核心
void Serial::USART(QString port, QString baud, QString data,QString stop,QString check) {
    QSerialPort::BaudRate Baud;     //波特率
    QSerialPort::DataBits Data;     //数据位
    QSerialPort::StopBits Stop;     //停止位
    QSerialPort::Parity Check;      //校验位

    if (baud == "4800")  Baud = QSerialPort::Baud4800;
    else if (baud == "9600") Baud = QSerialPort::Baud9600;
    else if (baud == "19200")  Baud = QSerialPort::Baud19200;
    
    if (data == "8") Data = QSerialPort::Data8;

    if (stop == "1") Stop = QSerialPort::OneStop;
    else if (stop == "1.5")Stop = QSerialPort::OneAndHalfStop;
    else if (stop == "2") Stop = QSerialPort::TwoStop;

    if (check == QString::fromLocal8Bit("无")) Check = QSerialPort::NoParity;
    else if (check == QString::fromLocal8Bit("奇校验")) Check = QSerialPort::OddParity;
    else if (check == QString::fromLocal8Bit("偶校验")) Check = QSerialPort::EvenParity;

    serialPort = new QSerialPort(this);
    //为串口设置配置
    serialPort->setBaudRate(Baud);
    serialPort->setPortName(port);
    serialPort->setDataBits(Data);
    serialPort->setParity(Check);
    serialPort->setStopBits(Stop);
    //打开串口
    if (serialPort->open(QSerialPort::ReadWrite)) {
        //配置信号槽,一旦收到数据则开始读取
        QObject::connect(serialPort, &QSerialPort::readyRead, [&]() {
            auto data = serialPort->readAll();
            if (receiveMode->currentText() == "HEX") {      //字节模式
                QString hex = data.toHex(' ');
                receiveAera->appendPlainText(hex);
            }
            else {                                          //文本模式
                QString str = QString(data);
                receiveAera->appendPlainText(str);
            }
            });
    }else {
        QMessageBox::critical(this, QString::fromLocal8Bit("串口打开失败"), QString::fromLocal8Bit("请确认串口是否正确连接"));
    }
}

//刷新可用串口
void Serial::RefreshPort(void) {
    QVector<QString>temp;
    //获取当前可用串口号
    for (const QSerialPortInfo& info : QSerialPortInfo::availablePorts()) {
        temp.push_back(info.portName());
    }
    //排序现有的串口号,用于比较和原有的差距
    qSort(temp.begin(), temp.end());
    if (temp != this->ports) {  //如果可用串口号有变化
        this->portNumber->clear();  //清除原有列表
        this->ports = temp;         //更新串口列表
        for (auto& a : ports) {     //更新新串口
            this->portNumber->addItem(a);
        }
    }
}

//接收区初始化
void Serial::ReceiveAeraInit(QWidget* parent) {
    receiveAera = new QPlainTextEdit(parent);
    receiveAera->setFixedSize(800,400);
    receiveAera->move(30,20);
    receiveAera->setReadOnly(true);     //接收区改为只读

    QPushButton* clearReceive = new QPushButton(QString::fromLocal8Bit("清空接收区"),parent);
    clearReceive->setFixedSize(150,50);
    clearReceive->move(680,430);
    //为清空接收区设置信号槽
    QObject::connect(clearReceive, &QPushButton::clicked, [&]() {
        receiveAera->clear();
        });
}

//发送区初始化
void Serial::SendAeraInit(QWidget* parent) {
    sendAera = new QPlainTextEdit(parent);
    sendAera->setFixedSize(800,100);
    sendAera->move(30,500);

    QPushButton* clearSend = new QPushButton(QString::fromLocal8Bit("清空发送区"), parent);
    clearSend->setFixedSize(150, 50);
    clearSend->move(680, 630);
    QObject::connect(clearSend, &QPushButton::clicked, [&]() {
        sendAera->clear();
        });

    sendButton = new QPushButton(QString::fromLocal8Bit("发送"), parent);
    sendButton->setFixedSize(150, 50);
    sendButton->move(500, 630);
    sendButton->setDisabled(true);
    QObject::connect(sendButton, &QPushButton::clicked, [&]() {
        QString data = sendAera->toPlainText();
        if (sendMode->currentText() == "HEX") {
            QByteArray arr;
            for (int i = 0; i < data.size(); i++){
                if (data[i] == ' ') continue;
                int num = data.mid(i, 2).toUInt(nullptr, 16);       //将数据转为16进制
                i++;
                arr.append(num);
            }
            serialPort->write(arr);
        }else {
            serialPort->write(data.toLocal8Bit().data());           //转为utf-8格式字符串写入
        }
        });
}

//定时事件
void Serial::timerEvent(QTimerEvent* e) {
    RefreshPort();      //更新端口     
}

//串口设置初始化
void Serial::SetupInit(QWidget* parent) {
    this->portNumber = new QComboBox(parent);
    this->baudRate = new QComboBox(parent);
    this->dataSize = new QComboBox(parent);
    this->stopSize = new QComboBox(parent);
    this->check = new QComboBox(parent);
    this->receiveMode = new QComboBox(parent);
    this->sendMode = new QComboBox(parent);

    this->baudRate->addItem("4800");
    this->baudRate->addItem("9600");
    this->baudRate->addItem("19200");
    this->dataSize->addItem("8");
    this->stopSize->addItem("1");
    this->stopSize->addItem("1.5");
    this->stopSize->addItem("2");
    this->check->addItem(QString::fromLocal8Bit("无"));
    this->check->addItem(QString::fromLocal8Bit("奇校验"));
    this->check->addItem(QString::fromLocal8Bit("偶校验"));
    this->receiveMode->addItem(QString::fromLocal8Bit("HEX"));
    this->receiveMode->addItem(QString::fromLocal8Bit("文本"));
    this->sendMode->addItem(QString::fromLocal8Bit("HEX"));
    this->sendMode->addItem(QString::fromLocal8Bit("文本"));

    QLabel* portLabel = new QLabel(QString::fromLocal8Bit("串口号"), parent);
    QLabel* baudLabel = new QLabel(QString::fromLocal8Bit("波特率"),parent);
    QLabel* dataLabel = new QLabel(QString::fromLocal8Bit("数据位"),parent);
    QLabel* stopLabel = new QLabel(QString::fromLocal8Bit("停止位"),parent);
    QLabel* checkLabel = new QLabel(QString::fromLocal8Bit("校验位"),parent);
    QLabel* receiveModeLabel = new QLabel(QString::fromLocal8Bit("接收格式"),parent);
    QLabel* sendModeLabel = new QLabel(QString::fromLocal8Bit("发送格式"),parent);

    QVector<QComboBox*>setups;
    setups.push_back(portNumber);
    setups.push_back(baudRate);
    setups.push_back(dataSize);
    setups.push_back(stopSize);
    setups.push_back(check);
    setups.push_back(receiveMode);
    setups.push_back(sendMode);

    QVector<QLabel*>labels;
    labels.push_back(portLabel);
    labels.push_back(baudLabel);
    labels.push_back(dataLabel);
    labels.push_back(stopLabel);
    labels.push_back(checkLabel);
    labels.push_back(receiveModeLabel);
    labels.push_back(sendModeLabel);

    for (int i = 0; i < setups.size(); ++i) {
        setups[i]->setFixedSize(200, 50);
        setups[i]->move(850, 20 + i * 80);
        labels[i]->move(1080,25+i*80);
    }

}

//串口连接
void Serial::BeginUSART(QWidget* parent) {
    startUSART = new QPushButton(QString::fromLocal8Bit("串口连接"),parent);
    endUSART = new QPushButton(QString::fromLocal8Bit("断开连接"),parent);
    endUSART->setFixedSize(150, 50);
    endUSART->move(1000, 600);
    startUSART->setFixedSize(150, 50);
    startUSART->move(850,600);
    endUSART->setDisabled(true);        //一开始没有连接串口,因此关闭按钮初始化为无效
    //为关闭连接按钮配置信号槽
    QObject::connect(endUSART, &QPushButton::clicked, [&]() {
        endUSART->setDisabled(true);        //使关闭连接按钮失效
        startUSART->setDisabled(false);     //使连接按钮生效
        sendButton->setDisabled(true);      //使发送按钮失效
        serialPort->close();                //断开串口连接
        });
    //为连接按钮配置信号槽
    QObject::connect(startUSART, &QPushButton::clicked, [&]() {
        QString port = portNumber->currentText();
        QString baud = baudRate->currentText();
        QString data = dataSize->currentText();
        QString stop = stopSize->currentText();
        QString ch = check->currentText();
        QString receive = receiveMode->currentText();
        QString send = sendMode->currentText();
        if (port != "") {       //当串口号不为空,即有效时
            endUSART->setDisabled(false);   //使关闭连接按钮生效
            sendButton->setDisabled(false); //使发送按钮生效
            startUSART->setDisabled(true);  //使连接按钮失效
            USART(port,baud,data,stop,ch);  //连接串口
        }
        });
}

Serial::Serial(QWidget *parent): QMainWindow(parent){
    this->setFixedSize(1200,750);
    this->setWindowTitle(QString::fromLocal8Bit("串口助手"));
    ReceiveAeraInit(this);
    SendAeraInit(this);
    SetupInit(this);
    BeginUSART(this);
    this->startTimer(1000);         //开个1秒的定时器用来扫描可用串口
}

Serial::~Serial(){

}
#pragma once
#include <QtWidgets/QMainWindow>
#include <QPlainTextEdit>
#include <QPushButton>
#include <QComboBox>
#include <QLabel>
#include <QTimer>
#include <QMessageBox>

#include <QSerialPortInfo>
#include <QSerialPort>

#include <qdebug.h>
#include <qvector.h>

class Serial : public QMainWindow{
    Q_OBJECT
public:
    Serial(QWidget *parent = nullptr);
    ~Serial();
    void RefreshPort(void);
    void timerEvent(QTimerEvent* e);
    void ReceiveAeraInit(QWidget* parent);
    void SendAeraInit(QWidget* parent);
    void SetupInit(QWidget* parent);
    void BeginUSART(QWidget* parent);

    void USART(QString port, QString baud, QString data, QString stop, QString ch);
private:
    QPlainTextEdit* sendAera;
    QPlainTextEdit* receiveAera;

    QPushButton* sendButton;

    QComboBox* portNumber;
    QComboBox* baudRate;
    QComboBox* dataSize;
    QComboBox* stopSize;
    QComboBox* check;
    QComboBox* receiveMode;
    QComboBox* sendMode;
    QPushButton* startUSART;
    QPushButton* endUSART;

    QSerialPort* serialPort;
    QVector<QString>ports;
};

效果展示

  • 22
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个使用C++Qt的串口发送工具的示例代码: 首先,在Qt Creator中新建一个Qt Widgets应用程序,然后在mainwindow.h文件中添加以下内容: ```c++ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QtSerialPort/QSerialPort> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: void on_openButton_clicked(); void on_sendButton_clicked(); void readData(); private: Ui::MainWindow *ui; QSerialPort *serial; }; #endif // MAINWINDOW_H ``` 在mainwindow.cpp文件中添加以下内容: ```c++ #include "mainwindow.h" #include "ui_mainwindow.h" #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 初始化串口 serial = new QSerialPort(this); serial->setBaudRate(QSerialPort::Baud9600); serial->setDataBits(QSerialPort::Data8); serial->setParity(QSerialPort::NoParity); serial->setStopBits(QSerialPort::OneStop); serial->setFlowControl(QSerialPort::NoFlowControl); // 信号槽连接 connect(serial, SIGNAL(readyRead()), this, SLOT(readData())); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_openButton_clicked() { if (serial->isOpen()) { // 如果串口已经打开了,就关闭 serial->close(); ui->openButton->setText(tr("打开串口")); } else { // 否则就打开串口 serial->setPortName(ui->portComboBox->currentText()); if (serial->open(QIODevice::ReadWrite)) { ui->openButton->setText(tr("关闭串口")); } else { qDebug() << serial->errorString(); } } } void MainWindow::on_sendButton_clicked() { QString data = ui->sendEdit->text(); serial->write(data.toLatin1()); } void MainWindow::readData() { QByteArray data = serial->readAll(); ui->recvEdit->append(QString(data)); } ``` 在mainwindow.ui文件中添加以下内容: - 添加一个QComboBox控件,用于选择串口号。 - 添加一个QPushButton控件,用于打开或关闭串口。 - 添加一个QLineEdit控件,用于输入要发送的数据。 - 添加一个QPushButton控件,用于发送数据。 - 添加一个QTextEdit控件,用于显示接收到的数据。 最后,我们需要在mainwindow.cpp文件中的构造函数中初始化串口的端口号,如下所示: ```c++ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 初始化串口 serial = new QSerialPort(this); serial->setPortName("COM1"); // 串口端口号 serial->setBaudRate(QSerialPort::Baud9600); serial->setDataBits(QSerialPort::Data8); serial->setParity(QSerialPort::NoParity); serial->setStopBits(QSerialPort::OneStop); serial->setFlowControl(QSerialPort::NoFlowControl); // 信号槽连接 connect(serial, SIGNAL(readyRead()), this, SLOT(readData())); } ``` 这样,我们就完成了一个基本的串口发送工具。您可以在此基础上进进一步的开发和扩展,例如添加设置串口参数的功能、显示发送和接收的数据等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值