赞
踩
上位机:指的是可以直接发送操作指令的计算机或者单片机,一般提供用户操作交互界面并向用户展示反馈数据。
典型设备:电脑、平板、手机、面板、触摸屏
下位机:指的是与机器相连接的计算机或者单片机,一般用于接收和反馈上位机的指令,并根据指令控制机器执行动作以及从机器传感器读取数据。
典型设备: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
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
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; }
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连接,两个模块都连接到电脑上,然后打开我们开发的上位机,选择其中一个端口进行连接,对于另一个模块,我们用常用的串口助手连接。这样我们点击开灯和关灯的按钮,正常会在另一个串口助手上收到相应的指令。
只要上位机这块的功能无误,下位机再按照这个指令去开发功能即可。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。