极速入门体验Qt5软件开发,从安装到打包,少走弯路,Qt入门指南,串口调试助手开发实战


前言

C语言学了这么久是否还跟我一样对着黑窗口体验与printf的极致交流,学了Python后似乎忘了C/C++也能开发图形化界面,直到揭开Qt神秘的面纱,才有相见恨晚的感觉。在此之前,都用Python开发上位机软件,语言简洁精炼,入门简单高效。但世界总是公平的,有舍就有的,有好处必然有坏处。其一,多次碰到程序卡顿的情况。其二,使用串口时若没有在退出前关闭,就会一直占用。其三,打包出来的可执行程序体积太大。以上三宗罪并不是不可解决,但纠其根本,在于脚本语言本身没有低级语言的稳定性和速度。个人开发者倒是无所谓,对于工程实践更多需要是稳定和流畅。

难学的东西学会了肯定是有好处的,于是开始探索C/C++开发图像化界面的道路。了解了MFC,是微软公司提供的一个类库,只针对Windows平台开发可视化界面,许多windows程序都是由它开发,入门了一两天,用起来还是挺痛苦的。知道被Qt吸引,以其跨平台,文档丰富而完善,入门轻松高效,界面优美大方等优势,无可挑剔。

不过对于初学者,C语言学得多,C++部分看得懂,学起来还是有一些门槛的。本文基于三天入门过程中走过的弯路,以先成功后学习的理念,总结出一篇完整开发串口调试助手的简单实践,让初学者少走弯路,快速体验完整开发流程,再去深入了解或研究其他高深内容。


提示:之所以写这篇文章,也是因为看了许多其他作者的文章大受益处,分享带来共赢

一、成果先行

在这里插入图片描述
此串口调试助手功能还是比较完善的,使用起来丝毫不卡顿,启动速度也相当优秀,可打包成绿色版和安装版,用来代替市面上的串口调试助手是个不错的选择。可最重要的是有了开发技术,随意添加任何其他功能或对界面进行优化。给它取名为QComTool

二、下载安装

1.安装QT

从官网下载安装包:https://download.qt.io/archive/qt/5.14/5.14.2/ 本文使用5.14.2版本,其他版本或许略有不同,尽量别下最新版,用最新版会走更多弯路。下载后直接运行安装。刚进入安装程序会要求输入注册账户,如果闲麻烦可以先断网,再运行安装程序,会自动跳过这一步,再去联网即可。
在这里插入图片描述
组件选择需特别注意,本文只需选择MinGW 7.30 64位系统,用来编译运行,其他组件可以根据需要勾选,由于篇幅限制不展开描述。
在这里插入图片描述
之后根据提示一路下一步即可。
在这里插入图片描述
安装成功后打开开始菜单栏打开Qt Creator软件,是用于应用程序开发的跨平台IDE。
在这里插入图片描述

三、项目开发实战

1.创建新项目

在这里插入图片描述
选择Qt Widgets应用程序
在这里插入图片描述
设置项目路径和名称
在这里插入图片描述
编译系统默认
在这里插入图片描述
基类选择QWidget
在这里插入图片描述
然后一路下一步。创建成功后,直接Ctrl + R编译运行,或者点击左下角小锤子即可出现空白窗口。
在这里插入图片描述

2.UI设计

工程项目目录很简洁,*。pro包含一些配置脚本,一个基类头文件和源文件再加主程序文件。最下面的是设计UI的文件。
在这里插入图片描述
打开UI设计文件,可以很方便的通过拖拽方式设计界面,并且配置属性和名称。
在这里插入图片描述
先添加三个主体框架,修改属性让边框更清晰,再点击阵列分布自动适应窗口大小并对齐。
在这里插入图片描述
其他部分同理,根据需要设计自己的界面,特别注意修改各个控件的名称方便写程序,可在右侧层次结构框架中直接单击修改。设计出以下界面。
在这里插入图片描述
若对这一步有困难,可以直接用记事本打开这个ui文件,复制以下代码,自动生成该界面。

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Widget</class>
 <widget class="QWidget" name="Widget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>757</width>
    <height>529</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Widget</string>
  </property>
  <layout class="QGridLayout" name="gridLayout">
   <item row="0" column="0">
    <widget class="QFrame" name="frame">
     <property name="frameShape">
      <enum>QFrame::Box</enum>
     </property>
     <property name="frameShadow">
      <enum>QFrame::Raised</enum>
     </property>
     <property name="lineWidth">
      <number>2</number>
     </property>
     <layout class="QVBoxLayout" name="verticalLayout">
      <item>
       <layout class="QFormLayout" name="formLayout_2">
        <property name="verticalSpacing">
         <number>20</number>
        </property>
        <item row="0" column="0">
         <widget class="QLabel" name="label">
          <property name="text">
           <string>串口号:</string>
          </property>
         </widget>
        </item>
        <item row="0" column="1">
         <widget class="QComboBox" name="comboBox_1"/>
        </item>
        <item row="1" column="0">
         <widget class="QLabel" name="label_2">
          <property name="text">
           <string>波特率:</string>
          </property>
         </widget>
        </item>
        <item row="1" column="1">
         <widget class="QComboBox" name="comboBox_2"/>
        </item>
        <item row="2" column="0">
         <widget class="QLabel" name="label_3">
          <property name="text">
           <string>校验位:</string>
          </property>
         </widget>
        </item>
        <item row="2" column="1">
         <widget class="QComboBox" name="comboBox_3"/>
        </item>
        <item row="3" column="0">
         <widget class="QLabel" name="label_4">
          <property name="text">
           <string>数据位:</string>
          </property>
         </widget>
        </item>
        <item row="3" column="1">
         <widget class="QComboBox" name="comboBox_4"/>
        </item>
        <item row="4" column="0">
         <widget class="QLabel" name="label_5">
          <property name="text">
           <string>停止位:</string>
          </property>
         </widget>
        </item>
        <item row="4" column="1">
         <widget class="QComboBox" name="comboBox_5"/>
        </item>
        <item row="5" column="0">
         <widget class="QLabel" name="label_6">
          <property name="text">
           <string>流控制:</string>
          </property>
         </widget>
        </item>
        <item row="5" column="1">
         <widget class="QComboBox" name="comboBox_6"/>
        </item>
        <item row="6" column="0">
         <widget class="QLabel" name="label_7">
          <property name="text">
           <string>字编码:</string>
          </property>
         </widget>
        </item>
        <item row="6" column="1">
         <widget class="QComboBox" name="comboBox_7"/>
        </item>
       </layout>
      </item>
      <item>
       <widget class="QPushButton" name="Btn_Serial_Open">
        <property name="text">
         <string>打开串口</string>
        </property>
       </widget>
      </item>
     </layout>
    </widget>
   </item>
   <item row="0" column="1">
    <widget class="QFrame" name="frame_2">
     <property name="frameShape">
      <enum>QFrame::Box</enum>
     </property>
     <property name="frameShadow">
      <enum>QFrame::Raised</enum>
     </property>
     <property name="lineWidth">
      <number>2</number>
     </property>
     <layout class="QVBoxLayout" name="verticalLayout_2">
      <item>
       <widget class="QTextEdit" name="RX_Text">
        <property name="tabChangesFocus">
         <bool>false</bool>
        </property>
        <property name="readOnly">
         <bool>true</bool>
        </property>
       </widget>
      </item>
      <item>
       <layout class="QHBoxLayout" name="horizontalLayout">
        <item>
         <widget class="QPushButton" name="Btn_Clear">
          <property name="text">
           <string>清空所有</string>
          </property>
          <property name="checkable">
           <bool>false</bool>
          </property>
          <property name="autoDefault">
           <bool>false</bool>
          </property>
          <property name="default">
           <bool>false</bool>
          </property>
          <property name="flat">
           <bool>false</bool>
          </property>
         </widget>
        </item>
        <item>
         <layout class="QHBoxLayout" name="RX_Box">
          <item>
           <widget class="QCheckBox" name="RX_CheckBox_Hex">
            <property name="text">
             <string>Hex</string>
            </property>
            <property name="checked">
             <bool>false</bool>
            </property>
           </widget>
          </item>
          <item>
           <widget class="QCheckBox" name="RX_CheckBox_Format">
            <property name="text">
             <string>日志格式</string>
            </property>
            <property name="checked">
             <bool>true</bool>
            </property>
           </widget>
          </item>
         </layout>
        </item>
       </layout>
      </item>
     </layout>
    </widget>
   </item>
   <item row="1" column="0" colspan="2">
    <widget class="QFrame" name="frame_Send">
     <property name="frameShape">
      <enum>QFrame::Box</enum>
     </property>
     <property name="frameShadow">
      <enum>QFrame::Raised</enum>
     </property>
     <property name="lineWidth">
      <number>2</number>
     </property>
     <layout class="QVBoxLayout" name="verticalLayout_3">
      <item>
       <widget class="QTextEdit" name="TX_Text"/>
      </item>
      <item>
       <layout class="QHBoxLayout" name="horizontalLayout_4">
        <item>
         <widget class="QPushButton" name="Btn_Send">
          <property name="text">
           <string>发送</string>
          </property>
          <property name="checkable">
           <bool>false</bool>
          </property>
          <property name="checked">
           <bool>false</bool>
          </property>
          <property name="autoDefault">
           <bool>false</bool>
          </property>
          <property name="default">
           <bool>false</bool>
          </property>
          <property name="flat">
           <bool>false</bool>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QFrame" name="frame_4">
          <property name="frameShape">
           <enum>QFrame::StyledPanel</enum>
          </property>
          <property name="frameShadow">
           <enum>QFrame::Raised</enum>
          </property>
          <layout class="QHBoxLayout" name="horizontalLayout_2">
           <item>
            <widget class="QCheckBox" name="Auto_Send">
             <property name="text">
              <string>自动发送</string>
             </property>
            </widget>
           </item>
           <item>
            <widget class="QSpinBox" name="Wait_ms">
             <property name="minimum">
              <number>1</number>
             </property>
             <property name="maximum">
              <number>10000</number>
             </property>
             <property name="value">
              <number>100</number>
             </property>
            </widget>
           </item>
           <item>
            <widget class="QLabel" name="label_9">
             <property name="text">
              <string>ms</string>
             </property>
            </widget>
           </item>
          </layout>
         </widget>
        </item>
        <item>
         <layout class="QHBoxLayout" name="TX_Box">
          <item>
           <widget class="QCheckBox" name="TX_CheckBox_Hex">
            <property name="text">
             <string>Hex</string>
            </property>
           </widget>
          </item>
          <item>
           <widget class="QLabel" name="TX_Num">
            <property name="text">
             <string>已发送:0</string>
            </property>
           </widget>
          </item>
          <item>
           <widget class="QLabel" name="RX_Num">
            <property name="text">
             <string>已接收:0</string>
            </property>
           </widget>
          </item>
          <item>
           <widget class="QPushButton" name="Btn_Clear_Num">
            <property name="text">
             <string>清零</string>
            </property>
            <property name="checkable">
             <bool>false</bool>
            </property>
            <property name="autoDefault">
             <bool>false</bool>
            </property>
            <property name="default">
             <bool>false</bool>
            </property>
            <property name="flat">
             <bool>false</bool>
            </property>
           </widget>
          </item>
         </layout>
        </item>
       </layout>
      </item>
     </layout>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

3.编写widget.h头文件

widget.h文件中加入以下方法和属性,其中,方法作为自定义槽函数,信号和槽是Qt中的核心概念,通俗的讲就是一个控件状态的改变(如按钮被点击)会发出特定信号,通过connect函数将信号连接到指定的槽函数中,有信号就能触发槽函数运行。

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QSerialPort>
#include <QTimer>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    QSerialPort Serial;
    QTimer time;
    quint64 RX_Cnt;
    quint64 TX_Cnt;
    void Set_TX_Hex(bool checked);
    void Check_TX_Text();
    void Clear_Num();
    void ComboBox_AddItems();
    void Serial_Receive();
    void Serial_Ready_Send();
    void Serial_Send();
    void Serial_Tab();
    bool Serial_Open();
    bool Serial_Close();
    void OnTimeOut();


private:
    Ui::Widget *ui;

};
#endif // WIDGET_H

这里报错,不存在串口模块
在这里插入图片描述
需要在pro文件中添加这个模块
在这里插入图片描述

4.编写widget.cpp源文件

这里添加函数实现以及配置各个信号与槽相连接

#include "widget.h"
#include "ui_widget.h"
#include <QSerialPortInfo>
#include <QMetaEnum>
#include <QTextCodec>
#include <QDateTime>
#include <QMessageBox>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("QComTool");
    ui->frame_Send->setMaximumHeight(300);

    RX_Cnt = TX_Cnt = 0;//计数清零
    ui->Btn_Send->setEnabled(false);

    //添加项目
    ComboBox_AddItems();
    //连接信号槽 当下位机发送数据QSerialPor会发送readyRead信号,定义槽Serial_Receive解析数据
    connect(&Serial,&QSerialPort::readyRead,this,&Widget::Serial_Receive);
    //打开串口按钮
    connect(ui->Btn_Serial_Open,&QPushButton::clicked,this,&Widget::Serial_Tab);
    //发送数据按钮
    connect(ui->Btn_Send,&QPushButton::clicked,this,&Widget::Serial_Ready_Send);
    //清空接收按钮
    connect(ui->Btn_Clear,&QPushButton::clicked, ui->RX_Text,&QTextEdit::clear);
    //数据清零按钮
    connect(ui->Btn_Clear_Num,&QPushButton::clicked,this,&Widget::Clear_Num);
    //切换发送为Hex
    connect(ui->TX_CheckBox_Hex,  &QCheckBox::toggled, this,&Widget::Set_TX_Hex);
    //发送框文本改变
    connect(ui->TX_Text,&QTextEdit::textChanged,this,&Widget::Check_TX_Text);
    //自动发送
    connect(&time,&QTimer::timeout,this,&Widget::Serial_Send);
    //自动发送的循环时间
    connect(ui->Wait_ms, QOverload<int>::of(&QSpinBox::valueChanged),
          [=](int i){time.setInterval(i);});//匿名函数
}

Widget::~Widget()
{
    delete ui;
}
//切换发送为Hex
void Widget::Set_TX_Hex(bool checked)
{
    if (checked)
    {
        //编码格式
        QByteArray code_name;
        code_name.append(ui->comboBox_7->currentText());
        QTextCodec *codec = QTextCodec::codecForName(code_name);
        //数据转换
        QByteArray Encoded_data = codec->fromUnicode(ui->TX_Text->toPlainText());
        QString ret(Encoded_data.toHex().toUpper());
        if(ret.length()%2 == 1)
        {
            ret.insert(ret.length()-1,"0");
        }
        int len = ret.length()/2;
        for(int i=0;i<len;i++)
        {
            ret.insert(2*i+i+2," ");
        }
        ui->TX_Text->setText(ret);
    }
    else
    {
        QString ret = ui->TX_Text->toPlainText();
        ret = ret.toUpper();//全部大写
        ret.remove(QRegExp("[^A-F0-9]"));//正则匹配删除非法字符
        QByteArray Data_Hex;
        Data_Hex.append(ret);
        QByteArray Data_Ascii = QByteArray::fromHex(Data_Hex);
        //编码格式
        QByteArray code_name;
        code_name.append(ui->comboBox_7->currentText());
        QTextCodec *codec = QTextCodec::codecForName(code_name);
        //数据转换
        QString Unicode_data = codec->toUnicode(Data_Ascii);
        ui->TX_Text->setText(Unicode_data);
    }
}
//校验发送框字符是否非法
void Widget::Check_TX_Text()
{
    if(ui->TX_CheckBox_Hex->isChecked())
    {
        QString ret1 = ui->TX_Text->toPlainText(),ret2;
        ret2 = ret1.toUpper();
        ret1.remove(QRegExp("[A-F0-9][A-F0-9]\\s"));//先去除合法Hex字符
        if(ret1.length() > 1)
        {
            ret2.remove(QRegExp("[^A-F0-9]"));//删除非法字符
            if(ret2.length()%2 == 1)
            {
                ret2.insert(ret2.length()-1,"0");
            }
            int len = ret2.length()/2;
            for(int i=0;i<len;i++)
            {
                ret2.insert(2*i+i+2," ");
            }
            ui->TX_Text->setText(ret2);
            ui->TX_Text->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor);
        }
    }
}
//下拉列表框添加项目
void Widget::ComboBox_AddItems()
{
    QMetaEnum metaEnum;
    QStringList strList;
    //comboBox_1 可用串口
    foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {
        ui->comboBox_1->addItem(info.portName());
    }
    //comboBox_2 波特率
    metaEnum = QMetaEnum::fromType<QSerialPort::BaudRate>();
    for (int i = 0; i < metaEnum.keyCount()-1; i++)
    {
        ui->comboBox_2->addItem(QString::number(metaEnum.value(i)));
    }
    ui->comboBox_2->setCurrentText(QString::number(QSerialPort::Baud115200));
    //comboBox_3 校验位
    strList<<"无"<<"奇校验"<<"偶校验"<<"为0"<<"为1";
    ui->comboBox_3->addItems(strList);
    strList.clear();
    //comboBox_4 数据位
    metaEnum = QMetaEnum::fromType<QSerialPort::DataBits>();
    for (int i = 0; i < metaEnum.keyCount()-1; i++)
    {
        ui->comboBox_4->addItem(QString::number(metaEnum.value(i)));
    }
    ui->comboBox_4->setCurrentText(QString::number(QSerialPort::Data8));
    //comboBox_5 停止位
    strList<<"1"<<"1.5"<<"2";
    ui->comboBox_5->addItems(strList);
    strList.clear();
    //comboBox_6 流控
    strList<<"无"<<"硬件"<<"软件";
    ui->comboBox_6->addItems(strList);
    strList.clear();
    //字符编码格式
    strList<<"GBK"<<"UTF-8";
    ui->comboBox_7->addItems(strList);
    strList.clear();
}
//数据清零
void Widget::Clear_Num()
{
    RX_Cnt = TX_Cnt = 0;
    ui->RX_Num->setText("已接收:"+QString::number(RX_Cnt));
    ui->TX_Num->setText("已发送:"+QString::number(TX_Cnt));
}
//接收数据
void Widget::Serial_Receive()
{
    QByteArray data = Serial.readAll();
    RX_Cnt += data.length();
    ui->RX_Num->setText("已接收:"+QString::number(RX_Cnt));
    if(ui->RX_CheckBox_Format->isChecked())//添加日志
    {
        QDateTime time = QDateTime::currentDateTime();
        QString current_date = time.toString("\n【yyyy.MM.dd hh:mm:ss.zzz 接收】\n");
        ui->RX_Text->insertPlainText(current_date);
    }
    if(ui->RX_CheckBox_Hex->isChecked())//Hex模式
    {
        uchar temp;
        QString Hex;
        for (int i = 0; i < data.size(); i++)
        {
            temp = data.at(i);
            if(temp < 0x10)Hex += "0";
            Hex += QString::number(temp,16).toUpper()+" ";
        }
        ui->RX_Text->insertPlainText(Hex);
    }
    else
    {
        //编码格式
        QByteArray code_name;
        code_name.append(ui->comboBox_7->currentText());
        QTextCodec *codec = QTextCodec::codecForName(code_name);
        QString Unicode_data = codec->toUnicode(data);
        ui->RX_Text->insertPlainText(Unicode_data);
    }
    ui->RX_Text->moveCursor(QTextCursor::End);
}
//发送数据准备工作
void Widget::Serial_Ready_Send()
{
    if(ui->Auto_Send->isChecked())//自动发送使能
    {
        if(ui->Btn_Send->text().operator==("发送"))//开始发送
        {
            ui->Btn_Send->setText("停止发送");
            time.setInterval(ui->Wait_ms->value());//循环时间
            time.start();
        }
        else
        {
            ui->Btn_Send->setText("发送");
            time.stop();
        }
    }
    else
    {
        Serial_Send();
    }
}
//发送数据
void Widget::Serial_Send()
{
    if(ui->Auto_Send->isChecked() == false &&
       ui->Btn_Send->text().operator==("停止发送"))//自动发送使能
    {
        ui->Btn_Send->setText("发送");
        time.stop();
        return;
    }
    QByteArray Data_QByteArray;
    if(ui->TX_CheckBox_Hex->isChecked())//Hex格式发送
    {
        QString ret = ui->TX_Text->toPlainText();
        ret = ret.toUpper();//全部大写
        ret.remove(QRegExp("[^A-F0-9]"));//正则匹配删除非法字符
        QByteArray Hex_Srting;
        Hex_Srting.append(ret);
        Data_QByteArray = QByteArray::fromHex(Hex_Srting);
    }
    else//字符串格式发送
    {
        //编码格式
        QByteArray code_name;
        code_name.append(ui->comboBox_7->currentText());
        QTextCodec *codec = QTextCodec::codecForName(code_name);
        //数据发送
        Data_QByteArray = codec->fromUnicode(ui->TX_Text->toPlainText());
    }
    if(Data_QByteArray.length() > 0)
    {
        if(Serial.write(Data_QByteArray) >= 0)
        {
            if(ui->RX_CheckBox_Format->isChecked())//如果开启日志模式
            {
                QDateTime time = QDateTime::currentDateTime();
                QString current_date = time.toString("\n【yyyy.MM.dd hh:mm:ss.zzz 发送】\n");
                current_date += ui->TX_Text->toPlainText();
                ui->RX_Text->insertPlainText(current_date);
                ui->RX_Text->moveCursor(QTextCursor::End);
            }
            TX_Cnt += Data_QByteArray.length();
            ui->TX_Num->setText("已发送:"+QString::number(TX_Cnt));
        }
        else
        {
            QMessageBox::critical(this, tr("错误"), tr("串口发送失败"));
        }

    }
}
//切换串口状态
void Widget::Serial_Tab()
{
    if(ui->Btn_Serial_Open->text().operator==("打开串口"))
    {
        if(Serial_Open())
        {
            ui->Btn_Serial_Open->setText("关闭串口");
            ui->Btn_Send->setEnabled(true);
            ui->Btn_Send->setText("发送");
            time.stop();
        }
        else
        {
            QMessageBox::critical(this, tr("错误"), tr("串口打开失败"));
        }
    }
    else
    {
        if(Serial_Close())
        {
            ui->Btn_Serial_Open->setText("打开串口");
            ui->Btn_Send->setEnabled(false);
        }
    }

}
//打开串口
bool Widget::Serial_Open()
{
    Serial.setParent(this);
    QString PortName = ui->comboBox_1->currentText();
    QString Temp_String;
    //这样我们就获取到 可用的串口名字了
    Serial.setPortName(PortName);
    if(Serial.isOpen())//如果串口已经打开了 先给他关闭了
    {
        Serial.clear();
        Serial.close();
    }
    if(Serial.open(QIODevice::ReadWrite))//用ReadWrite 的模式尝试打开串口
    {
        //波特率设置
        Serial.setBaudRate(ui->comboBox_2->currentText().toInt(),QSerialPort::AllDirections);//设置波特率和读写方向
        //校验位设置
        Temp_String = ui->comboBox_3->currentText();
        QSerialPort::Parity Serial_Parity;
        if(Temp_String.operator == ("无" ))
            Serial_Parity = QSerialPort::NoParity;
        else if (Temp_String.operator == ("奇校验"))
            Serial_Parity = QSerialPort::EvenParity;
        else if (Temp_String.operator == ("偶校验"))
            Serial_Parity = QSerialPort::OddParity;
        else if (Temp_String.operator == ("为0"))
            Serial_Parity = QSerialPort::SpaceParity;
        else if (Temp_String.operator == ("为1"))
            Serial_Parity = QSerialPort::MarkParity;
        else
            Serial_Parity = QSerialPort::UnknownParity;
        Serial.setParity(Serial_Parity);
        //数据位设置
        Temp_String = ui->comboBox_4->currentText();
        QSerialPort::DataBits Serial_DataBits;
        if(Temp_String.operator == ("5"))
            Serial_DataBits = QSerialPort::Data5;
        else if (Temp_String.operator == ("6"))
            Serial_DataBits = QSerialPort::Data6;
        else if (Temp_String.operator == ("7"))
            Serial_DataBits = QSerialPort::Data7;
        else if (Temp_String.operator == ("8"))
            Serial_DataBits = QSerialPort::Data8;
        else
            Serial_DataBits = QSerialPort::UnknownDataBits;
        Serial.setDataBits(Serial_DataBits);		//数据位
        //停止位
        Temp_String = ui->comboBox_5->currentText();
        QSerialPort::StopBits Serial_StopBits;
        if(Temp_String.operator == ("1"))
            Serial_StopBits = QSerialPort::OneStop;
        else if (Temp_String.operator == ("1.5"))
            Serial_StopBits = QSerialPort::OneAndHalfStop;
        else if (Temp_String.operator == ("2"))
            Serial_StopBits = QSerialPort::TwoStop;
        else
            Serial_StopBits = QSerialPort::UnknownStopBits;
        Serial.setStopBits(Serial_StopBits);
        //流控制
        Temp_String = ui->comboBox_6->currentText();
        QSerialPort::FlowControl Serial_FlowControl;
        if(Temp_String.operator == ("无"))
            Serial_FlowControl = QSerialPort::NoFlowControl;
        else if (Temp_String.operator == ("硬件"))
            Serial_FlowControl = QSerialPort::HardwareControl;
        else if (Temp_String.operator == ("软件"))
            Serial_FlowControl = QSerialPort::SoftwareControl;
        else
            Serial_FlowControl = QSerialPort::UnknownFlowControl;
        Serial.setFlowControl(Serial_FlowControl);
        return true;
    }
    return false;
}
//关闭串口
bool Widget::Serial_Close()
{
    if(Serial.isOpen())//关闭旧串口
    {
        Serial.clear();
        Serial.close();
        return true;
    }
    return false;
}

四、编译运行

到这里可能还有一些列报错,不过没关系,只要按照以上步骤,再点击编译后就不会报错。先给它添加一个图标,可将以下图片通过这个网站https://www.aconvert.com/cn/icon/jpg-to-ico/生成ICO图标,命名为QComTool.ico放到项目文件夹中,
请添加图片描述
再Pro文件中加入这一行代码添加图标资源RC_ICONS = QComTool.ico

在这里插入图片描述
Ctrl+R编译运行:
在这里插入图片描述

五、项目打包

1.编译发布版

选择发布版进行编译,同样Ctrl+R
在这里插入图片描述
于是正常了发布版程序
在这里插入图片描述
在这里插入图片描述
但此时这个程序还不能运行,需要链接动态库文件,也就是传说中的dll.

2.绿色版打包

新建一个目录,命名为QComTool
将exe文件放到这个目录中
在这里插入图片描述

在开始菜单栏中找到 MinGW
在这里插入图片描述
运行代码

windeployqt.exe 文件绝对路径\QComTool.exe

程序会自动将所有动态链接库复制到这个目录中
在这里插入图片描述
这样就得到了一个绿色版的程序,大功告成,点击exe即可运行。

3.安装版打包

如果还需要打包成安装版,可以使用工具 innosetup-6.2.1.exe 进行打包,官网下载链接:
https://jrsoftware.org/isinfo.php,只需通过这个工具把绿色版整个文件夹打包成安装包程序即可。

总结

通过本文实现了串口调试助手功能,但篇幅限制没有展开描述,相信有C++基础的基本能够看懂程序,更多功能等待探索。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

简单|纯粹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值