目录

手把手教你用Qt写一个上位机

手把手教你用Qt写一个上位机

关注+ 星标公众 ,不错过精彩内容

https://i-blog.csdnimg.cn/blog_migrate/9a45f63201704bf34cdc3da0c9ef9542.gif

转自 | 嵌入式大杂烩

对于嵌入式开发的小伙伴,用Qt写上位机是最常见的方法之一,对于有基础的朋友来来说,相对还是比较简单。

今天从编写一个简单的基于QT的上位机来体会体会上位机开发及认识认识QT。

我们本次实现的上位机的功能很简单:上位机通过串口来控制开发板上的一个LED的亮灭。界面如:

https://i-blog.csdnimg.cn/blog_migrate/fc04867d9ba05d29bf588c83d5d2d468.png

演示视频:

QT环境搭建

在开始编写上位机之前我们先来一起搭建一下QT开发环境(不然就不是手把手了,哈哈)。往期推文 QT | 详解Qt的几种开发方式 中有介绍到QT的两种开发环境:

  • 使用VS + QT
  • 使用Qt Creator

这里我们选择直接使用QT_Creator的方式。

Qt Creator是一个用于Qt开发的轻量级跨平台集成开发环境。

Qt Creator可带来两大关键益处:

  • 提供首个专为支持跨平台开发而设计的集成开发环境 (IDE),并确保首次接触Qt框架的开发人员能迅速上手和操作。
  • 即使不开发Qt应用程序,Qt Creator也是一个简单易用且功能强大的IDE。

下面我们来一起安装Qt Creator。

1、注册qt账号

我们需要先注册一个QT账号,后面安装Qt Creator的时候会用到。注册账号的地址为:

https://i-blog.csdnimg.cn/blog_migrate/a4bcaeff02f939f2f6f76b27b7e2e126.png

https://i-blog.csdnimg.cn/blog_migrate/8e02dbceb297784654e310a800541231.png

2、下载QT_Creator并安装

我们在Windows上进行开发,安装Windows版本的Qt Creator。下载地址:

https://i-blog.csdnimg.cn/blog_migrate/e00ecc523baf2ec569d24db8ba0ad8ac.png

下载得到qt-opensource-windows-x86-5.11.3.exe。然后双击安装,第二步需要输入账号密码,把我们上面注册好的账号密码填入即可。

接下来还需要选择安装组件,根据自己需要进行选择安装,我安装的组件如:

https://i-blog.csdnimg.cn/blog_migrate/4827fa88d52166be47634ba7bd33c6ff.png

安装完成之后我们桌面上并没有Qt Creator的快捷方式,需要自己创建。找到Qt Creator的安装路径,然后把Qt Creator发送到桌面快捷方式即可。如:

https://i-blog.csdnimg.cn/blog_migrate/dba3a78b6f38de4777559b60fb404e22.png

3、验证QT_Creator是否安装成功

我们创建一个简单的C++工程来验证一下Qt Creator是否安装成功。

https://i-blog.csdnimg.cn/blog_migrate/73f0029cd97aedbd2e0006734722bb4e.png

https://i-blog.csdnimg.cn/blog_migrate/7fd4d92932a944ee2ccbdc2d235cac22.png

https://i-blog.csdnimg.cn/blog_migrate/7af7a5a701c46fd52c88c5b9997d61e2.png

https://i-blog.csdnimg.cn/blog_migrate/26a4914cf7a95407fdcad781e30f6025.png

https://i-blog.csdnimg.cn/blog_migrate/bd6f37f53614a99263d384a3375af81b.png

Qt Creator搭建好之后我们接下来开始编写我们的上位机。

编写一个简单的上位机

编写这个简单的上位机我们需要经过一下几个步骤:

  • 上位机界面设计。
  • 上位机逻辑代码编写。
  • 添加上位机图标。
  • 上位机程序的打包。
  • 上位机测试验证。

1、新建一个serial_led工程

https://i-blog.csdnimg.cn/blog_migrate/0f7d85378312956b04b569af6d9ee617.png

https://i-blog.csdnimg.cn/blog_migrate/b26243e4be00ba8041501e1f207c35ae.png

https://i-blog.csdnimg.cn/blog_migrate/d039f7a8619f66b1cbccafc8205f93dc.png

https://i-blog.csdnimg.cn/blog_migrate/e4b7fa0418be384c8f89f37fe34f74e4.png

https://i-blog.csdnimg.cn/blog_migrate/482f7a3401ee307104f781582eb5e2b4.png

这里需要注意的一点是: 工程名及工程路径不要有中文字符

另外,QT中有三种基类,这里我们选择 QWidget类 。QT的三个基类如:

  • QMainWindow类:提供一个带有菜单条,工具条和一个状态条的主应用程序窗口。
  • QWidget类:所有用户界面对象的基类,窗口部件是用户界面的一个基本单元,它从窗口系统接收鼠标,键盘和其他消息,并在屏幕上绘制自己。
  • QDialog类:对话框窗口的基类,对话框窗口主要用于短期任务和用户进行短期通讯的顶级窗口,QDialog可以是模态对话框或者是非模态对话框。

我们创建的工程如:

https://i-blog.csdnimg.cn/blog_migrate/f692d19a75c74a49fbd7aa4ce11a85ef.png

其中,项目文件 .pro文件 是用来告诉 qmake 关于为这个应用程序创建 makefile 所需要的细节。例如,一个源文件和头文件的列表、任何应用程序特定配置。例如,一个必需链接的额外库或者一个额外的包含路径、都应该放到项目文件中。

2、上位机界面设计

Qt 一个可视化的界面设计工具:Qt 设计器(Qt Designer)。我们双击.ui文件就可以进入Qt Designer,在Qt Designer中我们可以通过拖动控件的方式来设计我们的界面,整个界面如:

https://i-blog.csdnimg.cn/blog_migrate/95635bf80233ac5b1c55394b94faf528.png

我们从左侧的控件区把我们需要的控件拖动到界面编辑区中,我们这个简单地上位机用到的控件如:

https://i-blog.csdnimg.cn/blog_migrate/4ce03f4cfe5e23374cdd93b685f120f2.png

这里需要注意的是波特率这个下拉框需要双击设置一些备选配置,如:

https://i-blog.csdnimg.cn/blog_migrate/d7880326be50e13377149d9df583890f.png

https://i-blog.csdnimg.cn/blog_migrate/a232f620a3ff97046ef46b9c0f145cd3.png

大家可以在左边地控件区找到这三种控件拖动到界面编辑器进行修改、布局即可。

其中,布局可通过如下组件调整:

https://i-blog.csdnimg.cn/blog_migrate/681a976c6ba9b27cf0fb4874d5a25348.png

这几个组件的功能如:

https://i-blog.csdnimg.cn/blog_migrate/1ac440e081ae3d097ee48e56e2193f80.png

具体地用法大家可以自己去实操一下。

另外,我们需要给我们使用的控件重新命名,在右侧的 对象管理区 进行操作。命名为有意义的名字,因为后面编写代码会用到。有意义的名字利于编写易懂的代码。比如我们修改的名字如:

https://i-blog.csdnimg.cn/blog_migrate/a2300a507f00498c442ab31176926625.png

最后,控件的属性可根据需要在属性区进行调整。

3、上位机逻辑代码编写

(1)添加串口库、包含串口相关头文件

serial_led.pro 文件添加串口库:

QT += core gui serialport

https://i-blog.csdnimg.cn/blog_migrate/1b09cb57979807b3ae9d0d81b50b7373.png

widget.h 文件包含串口头文件:

#include <QSerialPort>
#include <QSerialPortInfo>

https://i-blog.csdnimg.cn/blog_migrate/22d8a688e1fa63ac3d4074a3413ccf87.png

  • QSerialPort 类提供了操作串口的各种接口。
  • QSerialPortInfo 是一个辅助类,可以提供计算机中可用串口的各种信息。
(2)添加QSerialPort成员

在widget.h的Widget类中添加一个QSerialPort成员:

https://i-blog.csdnimg.cn/blog_migrate/5fc725c9be076855069bd83c017a650d.png

(3)创建串口对象、搜索所有可用串口

在Widget构造函数中创建一个串口对象并搜索所有可用串口:

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    QStringList serialNamePort;

ui->setupUi(this);
    this->setWindowTitle("serial_led");

/_  创建一个串口对象  _/
    serialPort = new QSerialPort(this);

/_  搜索所有可用串口  _/
    foreach (const QSerialPortInfo &inf0, QSerialPortInfo::availablePorts()) {
        serialNamePort<<inf0.portName();
    }
    ui->serialBox->addItems(serialNamePort);
}

https://i-blog.csdnimg.cn/blog_migrate/3f23709794be859ae4e87defe9f28c61.png

(4)编写“打开串口”槽函数

https://i-blog.csdnimg.cn/blog_migrate/04920ccec9e3a0ea2bd556dbefc292d0.png

https://i-blog.csdnimg.cn/blog_migrate/d5b97b1fbd8c75d22fa541a43c59ddcb.png

https://i-blog.csdnimg.cn/blog_migrate/c6439e399e80cea54ebe4e227b67dc2d.png

信号和槽是用于对象之间的通信,它是 Qt 的核心机制。

当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。如果有对象对这个信号感兴趣,想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。

这里,我们点击 打开串口 按钮会发出 clicked 信号 ,此时对应槽函数 on_openButton_clicked 会被调用。下面我们来实现这个槽函数:

void Widget::on_openButton_clicked()
{
    /_  串口设置  _/
    serialPort->setPortName(ui->serialBox->currentText());
    serialPort->setBaudRate(ui->baudrateBox->currentText().toInt());
    serialPort->setDataBits(QSerialPort::Data8);
    serialPort->setStopBits(QSerialPort::OneStop);
    serialPort->setParity(QSerialPort::NoParity);

/_  打开串口提示框  _/
    if (true == serialPort->open(QIODevice::ReadWrite))
    {
        QMessageBox::information(this, "提示", "串口打开成功");
    }
    else
    {
        QMessageBox::critical(this, "提示", "串口打开失败");
    }
}

这里我们写死数据位、停止位、求校验位;增加提示框。其中使用 QMessageBox 需要包含如下头文件:

#include <QMessageBox>
(5)编写“关闭串口”、“点灯”、“灭灯”槽函数

按照上面 打开串口 槽函数的方法编写 关闭串口点灯灭灯 槽函数:

void Widget::on_closeButton_clicked()
{
    serialPort->close();
}

void Widget::on_onButton_clicked()
{
    serialPort->write("ON\n");
    qDebug("ON\n");
}

void Widget::on_offButton_clicked()
{
    serialPort->write("OFF\n");
    qDebug("OFF\n");
}

以上就是上位机逻辑代码的编写。

4、添加上位机图标

在网上找一个相关的 .ico 后缀的图标下载放到我们的工程路径下,如:

https://i-blog.csdnimg.cn/blog_migrate/39f72ba9ff26490539323d7a481eb587.png

图标下载网址如:

然后在我们的 serial_led.pro 文件中添加如下一行代码:

RC_ICONS = led.ico

https://i-blog.csdnimg.cn/blog_migrate/f41622e7c971b83adca6410d01949a0b.png

5、上位机程序打包

我们上面运行的上位机都是在 Qt Creator 中编译运行的,如果我们需要把编写好的可执行文件发送给别人使用的话还需要进行打包。

上面我们的工程是 Debug 版本 的:

https://i-blog.csdnimg.cn/blog_migrate/ca9c9524f0fbb22272b023f86aade0bf.png

打包之前,我们先把工程修改为 Release 版本

https://i-blog.csdnimg.cn/blog_migrate/53ea4871d2fa8a5e70d72cfda344cfb6.png

然后在我们工程目录下得到:

https://i-blog.csdnimg.cn/blog_migrate/64b32217835c37278b43a1ce44115217.png

此时,双击 release 文件夹下的 serial_led.exe 文件是会报错的,报错原因是找不到一些相关的动态库:

https://i-blog.csdnimg.cn/blog_migrate/a55310cad60516b34b337452396d0223.png

我们新建一个文件夹保存我们的打包文件,如:

https://i-blog.csdnimg.cn/blog_migrate/3438f10ca606ba30c1b85f958a6e894a.png

把 build-serial_led-Desktop_Qt_5_11_1_MinGW_32bit-Release\release 路径下的 serial_led.exe 文件拷贝至 serial_led_packet 文件夹中:

https://i-blog.csdnimg.cn/blog_migrate/80e9298f2d7017e37db801b53cc914a1.png

打开 QT for Disktop 工具:

https://i-blog.csdnimg.cn/blog_migrate/0b2c97b9571c1db53778aec208ddcc71.png

https://i-blog.csdnimg.cn/blog_migrate/e065c6a63d56cbe60e13af562342d85c.png

执行如下命令进入打包目录:

cd /d D:\Qt\qt_prj\serial_led\serial_led_packet

然后执行如下命令进行打包:

windeployqt serial_led.exe

https://i-blog.csdnimg.cn/blog_migrate/c3d0c0dc76ce7fcb0ed69ded821c9af3.png

此时,serial_led_packet 文件夹中的 serial_led.exe 文件就可以双击运行了:

https://i-blog.csdnimg.cn/blog_migrate/29db33b90a2a98a1e33babc5a36d6f22.png

此时就完成了程序的打包。此时我们把这一整个文件夹压缩发送给别人使用了。另外,我们也可以借助一些工具把这些文件打包成一个整体的.exe 文件,这里不再介绍。

6、上位机测试验证

上位机我们写好了,接下来编写下位机代码来测试一下。

我们点击上位机的 点灯灭灯 按钮,则会通过串口分别发送 ON\nOFF\n ,我们编写下位机代码进行接收,然后操控 LED 灯即可。

下位机是 小熊派 IOT 开发板 ,测试代码如:

int main(void)
{
  /_ USER CODE BEGIN 1 _/

/_ USER CODE END 1 _/

/_ MCU Configuration----------------------------------------------------------_/

/_ Reset of all peripherals, Initializes the Flash interface and the Systick. _/
  HAL_Init();

/_ USER CODE BEGIN Init _/

/_ USER CODE END Init _/

/_ Configure the system clock _/
  SystemClock_Config();

/_ USER CODE BEGIN SysInit _/

/_ USER CODE END SysInit _/

/_ Initialize all configured peripherals _/
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  /_ USER CODE BEGIN 2 _/
  printf("Welcome to UART1 test!\r\n");

/_ USER CODE END 2 _/

/_ Infinite loop _/
  /_ USER CODE BEGIN WHILE _/
  while (1)
  {

/_ USER CODE END WHILE _/

/_ USER CODE BEGIN 3 _/ 
  if(HAL_UART_Receive(&huart1, &Rdata, 1, 0)==HAL_OK)
  {
      if (usart_rx_buf_index > USART1_RX_BUF_LEN - 1)
      {
        usart_rx_buf_index = 0;
      }

if (Rdata == 0x0A)
      {
        if (strcmp((char*)USART1_RX_BUF, "ON") == 0)
        {
          HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
        }
        else if (strcmp((char*)USART1_RX_BUF, "OFF") == 0)
        {
          HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
        }
        usart_rx_buf_index = 0;
        memset(USART1_RX_BUF, 0, USART1_RX_BUF_LEN);
      }
      else
      {
        USART1_RX_BUF[usart_rx_buf_index++] = Rdata;
      }
  }
  }
  /_ USER CODE END 3 _/

}

演示如文章开头所见。

总结

以上就是 手把手教你编写一个简单的点灯上位机 的内容,虽然实现的功能很简单,但是 QT 上位机开发的步骤基本就是这些步骤,通过这个基础实例把这些套路摸透我们就可以接着进行后续更多 QT 程序地开发学习了。

声明: 本文素材来源网络,版权归原作者所有。如涉及作品版权问题,请与我联系删除。


END

https://i-blog.csdnimg.cn/blog_migrate/b16a7f5cf31cd4b75bb4b332d5d9819e.gif

● 专栏《嵌入式工具

● 专栏《嵌入式开发》

● 专栏《Keil 教程》

● 嵌入式专栏精选教程

关注公众号回复“ 加群 ”按规则加入技术交流群,回复“ 1024 ”查看更多内容。

https://i-blog.csdnimg.cn/blog_migrate/a4d8af29157ed2db570e77f3160f14f7.jpeg

https://i-blog.csdnimg.cn/blog_migrate/9cba8e38004068b8baa8dfb0b375ac2b.png

点击“ 阅读原文 ”查看更多分享。