当前位置:   article > 正文

QT C++入门学习(2) QT Creator写一个简单的上位机控制LED_qt上位机

qt上位机

上位机和下位机的概念

上位机:指的是可以直接发送操作指令的计算机或者单片机,一般提供用户操作交互界面并向用户展示反馈数据。

典型设备:电脑、平板、手机、面板、触摸屏

下位机:指的是与机器相连接的计算机或者单片机,一般用于接收和反馈上位机的指令,并根据指令控制机器执行动作以及从机器传感器读取数据。

典型设备:PLC、stm32、51、FPGA、ARM等各类可编程芯片。

上位机软件:用于完成上位机操作交互的软件

  • 上位机给下位机发送控制命令,下位机接收到此命令并执行相应的动作;
  • 上位机给下位机发送状态获取命令,下位机接收到此命令后调用传感器测量,然后够转化为数字信息反馈给上位机。
  • 下位机主动发送状态信息或者报警信息给上位机

为了实现以上过程,上位机和下位机都需要独立进行编程,都需要专门的开发人员在各自的平台上编写代码。

上位机和下位机之间进行通信,常见的是有线连接,比如485,串口,USB等等,当然利用无线连接也可以,上位机和下位机的关系也有点类似主机和从机,通常上位机是电脑或平板,下位机是单片机设备。

编写程序

开发环境的搭建参考以往的文章:QT C++入门学习(1) QT Creator安装和使用

这里我们选择串口作为电脑端上位机软件与下位机的通信方式,串口作为嵌入式领域最常用的通信方式被广泛使用。

通信协议我们定义:AT+LED=ON\r\n 和 AT+LED=OFF\r\n 分别是开灯和关灯(\r\n是回车换行符,用来指示命令结尾)

1、新建一个serial_led工程
在这里插入图片描述
更改名称:
在这里插入图片描述
基类选择QWidget:
在这里插入图片描述
后面都是默认点下一步即可。
创建项目有疑问可以查看https://blog.csdn.net/weixin_44788542/article/details/130413466

完成后项目文件结构默认如下:
在这里插入图片描述
2、上位机界面设计
Qt 有一个可视化的界面设计工具:Qt 设计器(Qt Designer)。我们双击widget.ui文件就可以进入Qt Designer,在Qt Designer中我们可以通过拖动控件的方式来设计我们的界面
分别添加两个Label,两个Combo Box,和四个PushButton控件布局成如下图所示:
在这里插入图片描述
选中所有控件,点击栅格布局,已经放置的控件就自动对齐了。
在这里插入图片描述
默认的界面太大了,拉小一点:
在这里插入图片描述
3、完善控件参数
双击波特率对应的Combo Box,点击加号新增两个常用的波特率9600和115200备选项
在这里插入图片描述
选中控件,然后在右下角的对象名称属性那里更改名称
在这里插入图片描述
逐一按下图更改对象名称:
在这里插入图片描述
4、编写程序:
打开serial_led.pro文件,在第一行添加serialport
在这里插入图片描述

QT       += core gui serialport
  • 1

widget.h文件编写

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QSerialPort>
#include <QSerialPortInfo>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
    QSerialPort *serialPort;//定义串口指针
private slots:

    /*以下为widget.ui文件中点击“转到槽”自动生成的函数*/
    void on_openBt_clicked();

    void on_btnSerialCheck_clicked();

    void on_btnLedOn_clicked();

    void on_btnLedOff_clicked();

};
#endif // WIDGET_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

widget.cpp文件编写

#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("serial_led");

    QStringList serialNamePort;

    serialPort = new QSerialPort(this);

    ui->serailCb->clear();
    //通过QSerialPortInfo查找可用串口
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        ui->serailCb->addItem(info.portName());
    }

}

//检测通讯端口槽函数
void Widget::on_btnSerialCheck_clicked()
{
    ui->serailCb->clear();
    //通过QSerialPortInfo查找可用串口
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        ui->serailCb->addItem(info.portName());
    }
}

/*打开串口*/
void Widget::on_openBt_clicked()
{

    // 初始化串口属性,设置 端口号、波特率、数据位、停止位、奇偶校验位数
    serialPort->setPortName(ui->serailCb->currentText());
    serialPort->setBaudRate(ui->baundrateCb->currentText().toInt());
    serialPort->setDataBits(QSerialPort::Data8);
    serialPort->setStopBits(QSerialPort::OneStop);
    serialPort->setParity(QSerialPort::NoParity);

    // 根据初始化好的串口属性,打开串口
    // 如果打开成功,反转打开按钮显示和功能。打开失败,无变化,并且弹出错误对话框。
    if(ui->openBt->text() == "打开串口"){
        if(serialPort->open(QIODevice::ReadWrite) == true){
            ui->openBt->setText("关闭串口");
            // 让端口号下拉框不可选,避免误操作(选择功能不可用,控件背景为灰色)
            ui->serailCb->setEnabled(false);
        }else{
            QMessageBox::critical(this, "错误提示", "串口打开失败!!!\r\n该串口可能被占用\r\n请选择正确的串口");
        }
    }else{
        serialPort->close();
        ui->openBt->setText("打开串口");
        // 端口号下拉框恢复可选,避免误操作
        ui->serailCb->setEnabled(true);
    }

}

void Widget::on_btnLedOn_clicked()
{
    serialPort->write("AT+LED=ON\r\n");
}

void Widget::on_btnLedOff_clicked()
{
    serialPort->write("AT+LED=OFF\r\n");
}

Widget::~Widget()
{
    delete ui;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80

main.cpp不需要改动。

5、添加上位机图标
在网上找一个相关的.ico后缀的图标下载放到我们的工程路径下,如:
在这里插入图片描述
免费的ico文件下载参考该文:https://zhuanlan.zhihu.com/p/431105940
推荐https://www.iconfinder.com/

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

RC_ICONS = serial_led.ico

注意后面的文件名就是放在工程目录下的ico文件名
在这里插入图片描述
点击三角符号运行程序
在这里插入图片描述
界面左上角的图标就是我们放入的ico图标
在这里插入图片描述
这个图标还将作为打包生成的exe文件的图标。

后续打包的过程在另一文章有介绍,这里不赘述。传送门:QT如何打包生成独立可执行.exe文件

测试验证

实际工作中,我们自己开发好上位机,需要等下位机弄好后与之联调测试,如果下位机未准备好,我们可以自己先尽可能自测。
比如我这里用了两个USB转串口模块,两个模块的GND连接,TX和RX连接,两个模块都连接到电脑上,然后打开我们开发的上位机,选择其中一个端口进行连接,对于另一个模块,我们用常用的串口助手连接。这样我们点击开灯和关灯的按钮,正常会在另一个串口助手上收到相应的指令。
只要上位机这块的功能无误,下位机再按照这个指令去开发功能即可。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/133010
推荐阅读
  

闽ICP备14008679号