我們本次實現的上位機的功能很簡單:上位機通過串口來控制開發板上的一個LED的亮滅。界面如:
二、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的時候會用到。
2、下載QT_Creator并安裝
我們在Windows上進行開發,安裝Windows版本的Qt Creator。
下載得到qt-opensource-windows-x86-5.11.3.exe。然后雙擊安裝,第二步需要輸入賬號密碼,把我們上面注冊好的賬號密碼填入即可。
接下來還需要選擇安裝組件,根據自己需要進行選擇安裝,我安裝的組件如:
安裝完成之后我們桌面上并沒有Qt Creator的快捷方式,需要自己創建。找到Qt Creator的安裝路徑,然后把Qt Creator發送到桌面快捷方式即可。如:
3、驗證QT_Creator是否安裝成功
我們創建一個簡單的C++工程來驗證一下Qt Creator是否安裝成功。
Qt Creator搭建好之后我們接下來開始編寫我們的上位機。
三、編寫一個簡單的上位機
編寫這個簡單的上位機我們需要經過一下幾個步驟:
上位機界面設計。
上位機邏輯代碼編寫。
添加上位機圖標。
上位機程序的打包。
上位機測試驗證。
1、新建一個serial_led工程
這里需要注意的一點是:工程名及工程路徑不要有中文字符。
另外,QT中有三種基類,這里我們選擇QWidget類。QT的三個基類如:
QMainWindow類:提供一個帶有菜單條,工具條和一個狀態條的主應用程序窗口。
QWidget類:所有用戶界面對象的基類,窗口部件是用戶界面的一個基本單元,它從窗口系統接收鼠標,鍵盤和其他消息,并在屏幕上繪制自己。
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?#include?
?
?
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<serialBox->addItems(serialNamePort); }
?
?
(4)編寫“打開串口”槽函數
當某個事件發生之后,比如,按鈕檢測到自己被點擊了一下,它就會發出一個信號(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?
(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燈即可。
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程序地開發學習了。
編輯:黃飛
?
評論
查看更多