Qt小項目之串口助手控制LED


Qt小項目之串口助手控制LED

前言

最近剛學了一點Qt開發上位機,嘗試着做個小軟件練練手。查找了很多資料,做了一個簡單的串口助手,可以實現串口基本發送和接收功能,支持中文顯示,還可以控制STM32開發板上的兩個LED。

1.軟件界面

2.主要功能:

  • 啟動自動搜索本機串口,或者手動點擊搜索鍵掃描串口
  • 自定義波特率
  • 支持中文顯示
  • 支持發送新行

3.實際效果:

花了大概3天時間吧,找了很多資料,功能很簡單, 但想着是自己一點一點開發的,還是挺有成就感的哈!

寫這篇文章是為了總結一下開發的過程和一些知識點,主要包括兩部分,上位機的實現和STM32端程序的實現。

Qt上位機的實現

0.新建一個Dialog項目

新建一個Dialog項目,這3種基類的區別可以根據你的程序來確定。

  • 如果需要嵌入到其他窗體中,則基於QWidget創建。
  • 如果是主窗體,則基於QMainWindow創建,有菜單欄,狀態欄,工具欄等。
  • 如果是頂級對話框,則基於QDialog創建。

1.軟件UI界面的設計

使用Qt Designer添加所需要的控件,並進行合理布局,盡量每一個控件,起一個合理易懂的名字。

2.串口庫的添加

pro文件添加一行:

QT += serialport

對應的頭文件包含:

#include <QSerialPort>
#include <QSerialPortInfo>

3.串口自動搜索功能的實現

自動搜索本機串口,並在ComboBox中添加串口號

ui->cbb_com->clear();
//運行開始查找可用串口
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
    ui->cbb_com->addItem(info.portName());  //串口號下拉菜單,增加一個條目,為串口號COM4
    qDebug() << "串口搜索完成";
}

4.串口的配置和打開關閉

//打開串口按鈕
void Dialog::on_btn_uart_Ctrl_clicked()
{
//    static bool flag;   //也可以用標志位實現
    if(this->ui->btn_uart_Ctrl->text() == "打開串口")   //初始狀態,配置串口參數
    {
        serial.setPortName(ui->cbb_com->currentText());     //設置串口號、
        serial.setBaudRate(ui->cbb_baud->currentText().toInt());    //設置波特率
        serial.setDataBits(QSerialPort::Data8);     //設置串口數據位8
        serial.setParity(QSerialPort::NoParity);    //無校驗位
        serial.setStopBits(QSerialPort::OneStop);   //1位停止位
        serial.setFlowControl(QSerialPort::NoFlowControl);
        //打開串口
        if(!serial.open(QIODevice::ReadWrite))
        {
            QMessageBox::critical(NULL, "提示", "串口打開失敗");
            return;
        }
        qDebug() << "串口打開成功";
        this->ui->btn_uart_Ctrl->setText("關閉串口");
    }
    else
    {
        //關閉串口
        serial.close();
        this->ui->btn_uart_Ctrl->setText("打開串口");
    }
}

5.串口發送數據

    serial.write("A1\n");     //串口發送A1

6.串口數據的接收和顯示,支持中文

QT默認的編碼是unicode,不能顯示中文的,windows默認使用(GBK/GB2312/GB18030),使用了fromLocal8Bit()函數,實現了從Unicode到本地字符集GBK的轉換,用於處理漢語顯示亂碼等問題

槽函數的實現:

//串口數據接收並顯示
void Dialog::serialPort_readyRead()
{
    QByteArray rx_buf = serial.readAll();   //讀取串口接收的數據
    if(rx_buf.endsWith("\r\n")) //判斷接收最后是否是回車換行,即接收完成標志
    {

    }
    QString rx_buf_tmp = QString::fromLocal8Bit(rx_buf);    //轉換為中文格式
    qDebug() << rx_buf_tmp;         //控制台輸出

    ui->tb_rx_buf->append(rx_buf_tmp);

    rx_buf_tmp.clear();
    rx_buf.clear();
}

connect語句:

connect(&serial, & QSerialPort::readyRead, this, &Dialog::serialPort_readyRead);

7.下拉框自定義波特率的實現

//自定義波特率
void Dialog::on_cbb_baud_currentIndexChanged(const QString &arg1)
{
    if(this->ui->cbb_baud->currentIndex() == 3)
    {
        this->ui->cbb_baud->setItemText(3, ""); //調成自定義波特率時,內容設置為空,准備接收輸入
        this->ui->cbb_baud->setEditable(true);
    }
    else
    {
        this->ui->cbb_baud->setItemText(3, "自定義"); //調成自定義波特率時,內容設置為空,准備接收輸入
        this->ui->cbb_baud->setEditable(false);
    }
    serial.setBaudRate(ui->cbb_baud->currentText().toInt());    //即使打開串口后,仍然可以設置波特率
}

8.發送新行功能的實現

通過一個全局變量實現,發送新行按鈕勾選時,標志位置1,然后發送按鈕功能里,根據標志位決定是否在末尾添加換行符。

對應的槽函數實現:

//是否發送新行
void Dialog::on_cb_send_enter_clicked()
{
    if(ui->cb_send_enter->isChecked())
    {
        send_enter_flag = true;
        qDebug() << "發送新行";
    }
    else
    {
        send_enter_flag = false;
        qDebug() << "不發送新行";
    }
}
//發送按鈕被按下
void Dialog::on_btn_send_clicked()
{
    //獲取多行輸入框的數據並轉換為UTF8格式
    QByteArray tx_buf = ui->te_tx_buf->toPlainText().toUtf8();

    if(send_enter_flag == true)
        tx_buf += "\n";

    serial.write(tx_buf);     //把數據通過串口發送出去
    tx_buf.clear();
}

9.只改變標簽顏色

本來想着通過改變樣式表的方式改變顏色

    this->ui->lbe_blue->setStyleSheet("color: rgb(255, 0, 0);");

但是,實際運行時,連字體和大小都改成了默認的,有沒有一種只改變顏色其他的格式不變的方法呢?還真有,如下,不過好像只支持標准顏色?

	QPalette colr;
    colr.setColor(QPalette::WindowText,Qt::red);    //設置標簽顏色紅色
    this->ui->lbe_red->setPalette(colr);

10.按鈕的使能失能控制

以下兩行語句效果相同,都是失能按鈕功能:

this->ui->btn_led1_Ctrl->setDisabled(true); //LED控制按鈕不可用
this->ui->btn_led1_Ctrl->setEnabled(false); //LED控制按鈕不可用

11.文本顯示框設置最大顯示行數

this->ui->tb_rx_buf->document()->setMaximumBlockCount(10);

程序的圖標、標題設置和打包發布

你不希望窗口的標題是“Dialog”吧,所以添加一個標題和一個好看的圖標還是很有必要的。

1.添加標題

添加窗口標題還是很簡單的,一行代碼:

this->setWindowTitle("串口控制LED - By wcc ");

2.添加icon圖標

  • 找一個好看的圖標,格式一定要是.ico,像素大小推薦128*128
  • 命名為my_app.ico,名字無所謂,不要有中文就好了,放在工程目錄下,即和.pro文件和.cpp文件同一個目錄。
  • 打開.pro文件,最底下添加一行:RC_ICONS = my_app.ico

重新編譯就可以看到這種效果了。

3.程序文件的生成

構建選項改成Release版本,編譯完成后,會在Release目錄下生成一個.exe文件,把這個文件單獨拷出來放在一個空白的文件夾里,如D:\QT_Prj\Export\UART_Demo.exe,可以運行試一下,會提示缺少運行所需要的dll組件

而且,這個文件如果單獨拷貝到其他沒有安裝Qt環境的電腦上,也是不能運行的。

所以我們需要添加一些當前程序運行所需要的組件才能正常運行,但是需要添加哪些文件呢?不用擔心,Qt早已經想好了,運行MinGW工具:

先進入到exe文件所在的文件夾中:cd /d D:\QT_Prj\Export

然后輸入命令:windeployqt UART_Demo.exe

此時,打開exe文件所在的文件夾,可以看到Qt已經為我們添加好了,當前程序運行所需要的組件了。

這個時候,如果想給別人分享你開發好的上位機軟件,就可以直接把這個文件夾拷貝給他。當然也可以安裝一個Enigma Virtual Box軟件,把當前目錄下的所有文件打包成一個exe文件。

STM32端程序的實現

連接串口模塊,發送接收短接,可以看出Qt上位機的的收發都是正常的。下一步就是編寫STM32端的程序了,很簡單,當接收到字符串"A1"時,點亮紅燈;當接收到字符串“A2”時,熄滅紅燈;當接收到字符串“B1”時,點亮藍燈;當接收到字符串“B2”時,熄滅藍燈,每個字符串結尾都有換行符“\n”,即:

上位機發送 單片機執行
A1 紅燈點亮
A2 紅燈熄滅
B1 藍燈點亮
B2 藍燈熄滅

實現思路也很簡單,即把接收到的字符存入一個字符數組,當接收到“\n”換行標志時,意味着接收完成,判斷此時數組的內容,分別和命令比較,如果一致,執行相應的操作,串口1中斷服務函數:

void USART1_IRQHandler(void)
{
	char dat;
	char flag = 0;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)	//接收中斷
	{
		dat = USART1->DR;
		if(usart1Len >= 64)									//防止數據過多,導致內存溢出
			usart1Len = 0;
		if(dat == 0x0D || dat == 0x0A)		//回車換行,接收完成,此時的buf不含回車換行
		{
			if(strcmp(usart1Buf, "A2") == 0)	//字符串比較
			{
				UsartPrintf(USART1, "紅燈熄滅\r\n");
				GPIO_SetBits(GPIOB, GPIO_Pin_9);
			}
			else if(strcmp(usart1Buf, "A1") == 0)
			{
				UsartPrintf(USART1, "紅燈點亮\r\n");
				GPIO_ResetBits(GPIOB, GPIO_Pin_9);			
			}
			else if(strcmp(usart1Buf, "B2") == 0)
			{
				UsartPrintf(USART1, "藍燈熄滅\r\n");
				GPIO_SetBits(GPIOB, GPIO_Pin_6);			
			}			
			else if(strcmp(usart1Buf, "B1") == 0)
			{
				UsartPrintf(USART1, "藍燈點亮\r\n");
				GPIO_ResetBits(GPIOB, GPIO_Pin_6);			
			}	
			usart1Len = 0;
			memset(usart1Buf,0,64);
		}
		else
		{
			usart1Buf[usart1Len++] = dat;
		}
		USART_ClearFlag(USART1, USART_FLAG_RXNE);
	}
}

程序還是很簡單。板子是用的中移的麒麟座Mini板,基於F103C8T6的,串口1連接上位機,波特率115200,PB9-紅燈,PB6-綠燈,都是低電平點亮。

改進和優化的地方

  • 按鈕發送字符可自定義
  • 界面UI的設計優化
  • 數據波形的顯示
  • 發送和接收,16進制和字符模式的切換
  • 定時發送功能
  • 接收內容保存成文件
  • 一個小Bug,不支持多個串口的自動搜索。

Qt工程和STM32工程下載

Qt工程文件和STM32工程文件,還包括Enigma_Virtual_Box的安裝包,我都已經上傳CSDN資源,有需要的朋友可下載:qt_uart_demo.rar
當然,如果有朋友也在學習Qt開發上位機,歡迎互相交流學習。


歷史精選文章:


歡迎大家關注我的個人博客

或微信掃碼關注我的公眾號


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM