一、编写一个简单的上位机
编写这个简单的上位机我们需要经过一下几个步骤:
· 上位机界面设计。
· 上位机逻辑代码编写。
· 添加上位机图标。
· 上位机程序的打包。
· 上位机测试验证。
1、新建一个serial_led工程
这里需要注意的一点是:工程名及工程路径不要有中文字符。
另外,QT中有三种基类,这里我们选择QWidget类。QT的三个基类如:
1)QMainWindow类:提供一个带有菜单条,工具条和一个状态条的主应用程序窗口。
2)QWidget类:所有用户界面对象的基类,窗口部件是用户界面的一个基本单元,它从窗口系统接收鼠标,键盘和其他消息,并在屏幕上绘制自己。
3)QDialog类:对话框窗口的基类,对话框窗口主要用于短期任务和用户进行短期通讯的顶级窗口,QDialog可以是模态对话框或者是非模态对话框。
我们创建的工程如:
其中,项目文件.pro文件是用来告诉qmake关于为这个应用程序创建makefile所需要的细节。例如,一个源文件和头文件的列表、任何应用程序特定配置。例如,一个必需链接的额外库或者一个额外的包含路径、都应该放到项目文件中。
2、上位机界面设计
Qt 一个可视化的界面设计工具:Qt 设计器(Qt Designer)。我们双击.ui文件就可以进入Qt Designer,在Qt Designer中我们可以通过拖动控件的方式来设计我们的界面,整个界面如:
我们从左侧的控件区把我们需要的控件拖动到界面编辑区中,我们这个简单地上位机用到的控件如:
这里需要注意的是波特率这个下拉框需要双击设置一些备选配置,如:
大家可以在左边地控件区找到这三种控件拖动到界面编辑器进行修改、布局即可。
其中,布局可通过如下组件调整:
这几个组件的功能如:
具体地用法大家可以自己去实操一下。
另外,我们需要给我们使用的控件重新命名,在右侧的对象管理区进行操作。命名为有意义的名字,因为后面编写代码会用到。有意义的名字利于编写易懂的代码。比如我们修改的名字如:
最后,控件的属性可根据需要在属性区进行调整。
3、上位机逻辑代码编写
(1)添加串口库、包含串口相关头文件
在serial_led.pro文件添加串口库:
QT += core gui serialport
在widget.h文件包含串口头文件:
#include <QSerialPort> #include <QSerialPortInfo>
QSerialPort 类提供了操作串口的各种接口。
QSerialPortInfo 是一个辅助类,可以提供计算机中可用串口的各种信息。
(2)添加QSerialPort成员
在widget.h的Widget类中添加一个QSerialPort成员:
(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); }
(4)编写“打开串口”槽函数
信号和槽是用于对象之间的通信,它是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 "); qDebug("ON "); } void Widget::on_offButton_clicked() { serialPort->write("OFF "); qDebug("OFF "); }
以上就是上位机逻辑代码的编写。
4、添加上位机图标
在网上找一个相关的.ico后缀的图标下载放到我们的工程路径下,如:
图标下载网址如:
https://www.iconfont.cn/
https://www.iconfont.cn/
然后在我们的serial_led.pro文件中添加如下一行代码:
RC_ICONS = led.ico
5、上位机程序打包
我们上面运行的上位机都是在Qt Creator中编译运行的,如果我们需要把编写好的可执行文件发送给别人使用的话还需要进行打包。
上面我们的工程是Debug版本的:
打包之前,我们先把工程修改为Release版本:
然后在我们工程目录下得到:
此时,双击release文件夹下的serial_led.exe文件是会报错的,报错原因是找不到一些相关的动态库:
我们新建一个文件夹保存我们的打包文件,如:
把build-serial_led-Desktop_Qt_5_11_1_MinGW_32bit-Release elease路径下的serial_led.exe文件拷贝至serial_led_packet文件夹中:
打开QT for Disktop工具:
执行如下命令进入打包目录:
cd /d D:Qtqt_prjserial_ledserial_led_packet
然后执行如下命令进行打包:
windeployqt serial_led.exe
此时,serial_led_packet文件夹中的serial_led.exe文件就可以双击运行了:
此时就完成了程序的打包。此时我们把这一整个文件夹压缩发送给别人使用了。另外,我们也可以借助一些工具把这些文件打包成一个整体的.exe文件,这里不再介绍。
6、上位机测试验证
上位机我们写好了,接下来编写下位机代码来测试一下。
我们点击上位机的点灯、灭灯按钮,则会通过串口分别发送ON 、OFF ,我们编写下位机代码进行接收,然后操控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! "); /* 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程序地开发学习了。
来自公众号:嵌入式大杂烩
声明:转载此文是出于传递更多信息之目的。若有来源标注错误或侵犯了您的合法权益,请作者持权属证明与本网联系,我们将及时更正、删除,谢谢。