串口調試助手--Qt

来源:https://www.cnblogs.com/ghost-98210/archive/2019/08/17/11370710.html
-Advertisement-
Play Games

串口調試助手 該程式使用Qt框架,C ++語言編譯而成 項目文件介紹: 該文件中獲取串口是通過讀取Windows系統下的註冊表中的信息得到的, - 使用Qt中的定時器來每個3s讀取一次註冊表 串口通信方面:通過使用Qt的封裝的QSerialPort來實現 main.cpp mainwindow.h ...


串口調試助手----------該程式使用Qt框架,C ++語言編譯而成

項目文件介紹:

main.cpp            該文件為該程式的入口程式

mainwindow.h        該文件為該程式的主要聲明部分

mainwindow.cpp      該文件為該程式的主要定義部分

mainwindow.ui       該文件為該程式的ui界面設計

界面.png            界面的顯示效果

該文件中獲取串口是通過讀取Windows系統下的註冊表中的信息得到的, - 使用Qt中的定時器來每個3s讀取一次註冊表

串口通信方面:通過使用Qt的封裝的QSerialPort來實現

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSerialPort>
#include <QTimer>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    /*
     * 功能:獲取電腦中串口的埠
     * 參數:無
     * 返回值:無
     */
    void Get_Serial_Port(void);
    /*
     * 功能:當串口有數據的時候執行
     * 參數:無
     * 返回值:無
     */
    void readData(void);
    /*
     * 功能:每個3s執行的任務
     * 參數:無
     * 返回值:無
     */
    void myThread(void);

private slots:
    /*
     * 功能:點擊pushButton按鈕功能
     * 參數:無
     * 返回值:無
     */
    void on_pushButton_clicked();
    /*
     * 功能:點擊清空按鈕功能,清空顯示區的顯示
     * 參數:無
     * 返回值:無
     */
    void on_pushButton_2_clicked();

    void on_pushButton_3_clicked();

    void on_pushButton_4_clicked();

    void on_pushButton_5_clicked();

private:
    Ui::MainWindow  *ui;
    //串口類指針
    QSerialPort     *Serial;
    //時間類指針
    QTimer          *time;
};

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "windows.h"
#include "QVector"
#include "QDebug"
#include "stdio.h"
#include "QMessageBox"
#include <stdlib.h>

#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383

/*
 * 功能:讀取註冊表下的子項
 * 參數:hkey:註冊表的根
 *      lpSubkey:註冊表根下的路徑
 *      retArray:返回要查找的路徑下的值的數組
 * 返回值:無
 */
static void Get_Regedit(HKEY hkey,LPCSTR lpSubKey,QVector<QString> &retArray);

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //時間類初始化
    time = new QTimer(this);
    connect(time,&QTimer::timeout,this,&MainWindow::myThread);
    time->start(3000);
    //狀態欄顯示
    ui->statusBar->showMessage("程式運行中...");
    //初始化串口的顯示
    this->Get_Serial_Port();
    QStringList temp;
    //波特率的顯示
    temp << "9600" << "4800" << "19200" << "38400" << "57600" << "115200";
    ui->comboBox_2->addItems(temp);
    //數據位的顯示
    temp.clear();
    temp << "8" << "5" << "6" << "7";
    ui->comboBox_3->addItems(temp);
    //奇偶檢驗位的顯示
    temp.clear();
    temp << "0" << "1" << "2";
    ui->comboBox_4->addItems(temp);
    //停止位的顯示
    temp.clear();
    temp << "1" << "1.5" << "2";
    ui->comboBox_5->addItems(temp);

    this->Serial = new QSerialPort(nullptr);
}

MainWindow::~MainWindow()
{
    delete ui;
}
/*
 * 功能:獲取電腦中串口的埠
 * 參數:無
 * 返回值:無
 */
void MainWindow::Get_Serial_Port()
{
    QVector<QString> retArray;
    ui->comboBox->clear();
    Get_Regedit(HKEY_LOCAL_MACHINE,\
                "HARDWARE\\DEVICEMAP\\SERIALCOMM",\
                retArray);

    qDebug() << retArray.size();

    QVector<QString>::iterator iter;
    for (iter=retArray.begin();iter!=retArray.end();iter++)
    {
        qDebug() <<  *iter << "\0";
        ui->comboBox->addItem(*iter);
    }
}
/*
 * 功能:點擊pushButton按鈕功能,打開串口
 * 參數:無
 * 返回值:無
 */
void MainWindow::on_pushButton_clicked()
{
    if(!Serial->isOpen())
    {
        qDebug() << ui->comboBox->currentText();
        //設置串口的埠名稱
        Serial->setPortName(ui->comboBox->currentText());
        //toInt:將字元串轉換為數字
        //設置串口的波特率
        Serial->setBaudRate((ui->comboBox_2->currentText()).toInt(nullptr,10));
        //設置串口的數據位
        Serial->setDataBits((QSerialPort::DataBits((ui->comboBox_3->currentText()).toInt(nullptr,10))));
        //設置串口的奇偶校驗位
        Serial->setParity(QSerialPort::Parity((ui->comboBox_4->currentText()).toInt(nullptr,10)));
        //設置串口的停止位
        Serial->setStopBits(QSerialPort::StopBits((ui->comboBox_5->currentText()).toInt(nullptr,10)));
        //設置串口的流
        Serial->setFlowControl(QSerialPort::NoFlowControl);
        BOOL isSerial = Serial->open(QIODevice::ReadWrite);
        if(!isSerial)
        {
            qDebug() << "串口打開錯誤!";
            return;
        }
        //創建一個信號與槽,使得串口有數據可以讀取的時候可以執行readData()函數
        connect(Serial,&QSerialPort::readyRead,this,&MainWindow::readData);
        ui->pushButton->setText("已啟動");
    }
    else
    {
        ui->pushButton->setText("啟動");
        Serial->close();
    }

}

/*
 * 功能:讀取註冊表下的子項
 * 參數:hkey:註冊表的根
 *      lpSubkey:註冊表根下的路徑
 *      retArray:返回要查找的路徑下的值的數組
 * 返回值:無
 */
static void Get_Regedit(HKEY hkey,LPCSTR lpSubKey,QVector<QString> &retArray)
{
    HKEY  phkey = nullptr;
    BOOL isSuccess = false;
    /*
     * 功能:打開註冊表,返回值為是否打開成功
     */
    isSuccess = RegOpenKeyA(hkey,lpSubKey,&phkey);
    if(isSuccess != ERROR_SUCCESS)
    {
        qDebug() << "註冊表打開失敗!";
        return;
    }
    qDebug() << "註冊表打開成功!";
    /*
     * 功能:讀取註冊表下的子項
     */
    DWORD i =0;
    LSTATUS retCode = ERROR_SUCCESS;

    CHAR achValue[MAX_VALUE_NAME];
    DWORD cchValue = MAX_VALUE_NAME;
    BYTE Data[MAX_VALUE_NAME];
    DWORD cbData = MAX_VALUE_NAME;
    do
    {
        cchValue = MAX_VALUE_NAME;
        cbData = MAX_VALUE_NAME;
        achValue[0] = '\0';
        Data[0] = '\0';
        QString temp = "";
        retCode = RegEnumValueA(phkey, i,achValue,&cchValue,nullptr,nullptr,Data,&cbData);

        if (retCode == ERROR_SUCCESS && achValue[0] != '\0')
        {
            qDebug() << i++ << achValue << " ";
            BYTE j = 0;
            while(Data[j] != '\0')
                temp += (CHAR)(Data[j++]);
            qDebug() << temp;
            retArray.append(temp);
        }
    }while(achValue[0] != '\0');
    /*
     * 功能:關閉註冊表,返回值為是否打開成功
     */
    isSuccess = RegCloseKey(phkey);
    if(isSuccess != ERROR_SUCCESS)
    {
        qDebug() << "註冊表關閉失敗!";
        return;
    }
    qDebug() << "註冊表關閉成功!";
    return;
}

/*
 * 功能:點擊清空按鈕功能,清空顯示區的顯示
 * 參數:無
 * 返回值:無
 */
void MainWindow::on_pushButton_2_clicked()
{
    ui->textBrowser->setText("");
}

/*
 * 功能:當串口有數據的時候執行,在顯示區域顯示
 *      串口接受到的值
 * 參數:無
 * 返回值:無
 */
void MainWindow::readData(void)
{
    //是否選擇了該按鈕,選擇以16進位進行輸出
    if(ui->radioButton->isChecked())
    {
        QByteArray temp = Serial->readAll().toHex();
        for(int i = 0;i < temp.length();++i)
        {
            //在16進位開始加入"0x"
            if(i % 2 == 0)
                ui->textBrowser->insertPlainText("0x");
            ui->textBrowser->insertPlainText((QString)temp.at(i));
            //在16進位結束加上空格" "
            if(i % 2 == 1)
                ui->textBrowser->insertPlainText(" ");
        }
    }
    //沒有選擇則按照ASCII碼輸出
    else
        ui->textBrowser->insertPlainText(Serial->readAll());
    ui->textBrowser->moveCursor(QTextCursor::End);
}
/*
 * 功能:向串口中發送數據
 * 參數:無
 * 返回值:無
 */
void MainWindow::on_pushButton_3_clicked()
{
    //判斷串口是否處於打開狀態
    if(Serial->isOpen())
    {
        QByteArray temp = ui->textEdit->toPlainText().toUtf8();
        qDebug() << temp;
        Serial->write(temp);
    }
    else
    {
        //串口沒有連接的時候發送數據就會出錯
        QMessageBox messageBox(QMessageBox::Icon(2),"警告","串口未連接",QMessageBox::Yes,nullptr);
        messageBox.exec();
    }
}
/*
 * 功能:清空發送區
 * 參數:無
 * 返回值:無
 */
void MainWindow::on_pushButton_4_clicked()
{
    ui->textEdit->clear();
}
/*
 * 功能:退出程式
 * 參數:無
 * 返回值:無
 */
void MainWindow::on_pushButton_5_clicked()
{
    if(Serial->isOpen())
        Serial->close();
    this->close();
}
/*
 * 功能:每個3s執行的任務,判斷埠和串口是否打開
 * 參數:無
 * 返回值:無
 */
void MainWindow::myThread()
{
    qDebug() << "線程OK ";
    if(Serial->isReadable())
        ui->pushButton->setText("已啟動");
    else
        ui->pushButton->setText("啟動");
    this->Get_Serial_Port();
}
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>768</width>
    <height>500</height>
   </rect>
  </property>
  <property name="minimumSize">
   <size>
    <width>768</width>
    <height>500</height>
   </size>
  </property>
  <property name="maximumSize">
   <size>
    <width>768</width>
    <height>500</height>
   </size>
  </property>
  <property name="windowTitle">
   <string>串口助手</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <widget class="QPushButton" name="pushButton">
    <property name="geometry">
     <rect>
      <x>20</x>
      <y>230</y>
      <width>93</width>
      <height>28</height>
     </rect>
    </property>
    <property name="text">
     <string>啟動</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton_2">
    <property name="geometry">
     <rect>
      <x>120</x>
      <y>290</y>
      <width>93</width>
      <height>28</height>
     </rect>
    </property>
    <property name="text">
     <string>清空顯示</string>
    </property>
   </widget>
   <widget class="QComboBox" name="comboBox">
    <property name="geometry">
     <rect>
      <x>120</x>
      <y>50</y>
      <width>87</width>
      <height>22</height>
     </rect>
    </property>
   </widget>
   <widget class="QComboBox" name="comboBox_2">
    <property name="geometry">
     <rect>
      <x>120</x>
      <y>80</y>
      <width>87</width>
      <height>22</height>
     </rect>
    </property>
   </widget>
   <widget class="QComboBox" name="comboBox_3">
    <property name="geometry">
     <rect>
      <x>120</x>
      <y>110</y>
      <width>87</width>
      <height>22</height>
     </rect>
    </property>
   </widget>
   <widget class="QComboBox" name="comboBox_4">
    <property name="geometry">
     <rect>
      <x>120</x>
      <y>140</y>
      <width>87</width>
      <height>22</height>
     </rect>
    </property>
   </widget>
   <widget class="QComboBox" name="comboBox_5">
    <property name="geometry">
     <rect>
      <x>120</x>
      <y>170</y>
      <width>87</width>
      <height>22</height>
     </rect>
    </property>
   </widget>
   <widget class="QRadioButton" name="radioButton">
    <property name="geometry">
     <rect>
      <x>0</x>
      <y>295</y>
      <width>115</width>
      <height>19</height>
     </rect>
    </property>
    <property name="text">
     <string>以16進位輸出</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton_3">
    <property name="geometry">
     <rect>
      <x>120</x>
      <y>360</y>
      <width>93</width>
      <height>28</height>
     </rect>
    </property>
    <property name="text">
     <string>發送</string>
    </property>
   </widget>
   <widget class="QGroupBox" name="groupBox">
    <property name="geometry">
     <rect>
      <x>230</x>
      <y>4</y>
      <width>551</width>
      <height>331</height>
     </rect>
    </property>
    <property name="title">
     <string>接受顯示區</string>
    </property>
    <widget class="QTextBrowser" name="textBrowser">
     <property name="geometry">
      <rect>
       <x>10</x>
       <y>20</y>
       <width>521</width>
       <height>301</height>
      </rect>
     </property>
    </widget>
   </widget>
   <widget class="QGroupBox" name="groupBox_2">
    <property name="geometry">
     <rect>
      <x>230</x>
      <y>340</y>
      <width>541</width>
      <height>121</height>
     </rect>
    </property>
    <property name="title">
     <string>發送顯示區</string>
    </property>
    <widget class="QTextEdit" name="textEdit">
     <property name="geometry">
      <rect>
       <x>10</x>
       <y>20</y>
       <width>521</width>
       <	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 迭代器模式 定義 提供一種方法順序訪問一個聚合對象中各個元素,而又不暴露該對象的內部表示。 什麼時候用? 當你需要訪問一個聚集對象,而且不管這些對象是什麼都需要遍歷的時候,你就應該考慮用迭代器模式 。 你需要對聚集有多種方式遍歷時,可以考慮用迭代器模式。 UML圖 模板代碼 Aggregate It ...
  • 前言 我們目前已經學習了設計模式的7種設計原則。下麵本該是直接進入具體的設計模式系列文章。 但是呢在我們學習設計模式之前我們還是有必要瞭解一下uml圖。因為後續的設計模式文章不出意外應該會很多地方使用到uml圖。如果你連uml圖都看不懂的話,那麼學習起來肯定會有一定的難度。 所以說,這一節就作為承上 ...
  • 1. new一個對象在Java內部做了哪些工作? 從靜態角度來看,new一個對象表示創建一個類的對象實例。 從JVM運行角度來看,當JVM執行到new位元組碼時,首先會去查看類有沒有被載入到記憶體以及初始化,如果是第一次使用該類,則首先載入該類。載入完成後便會在堆記憶體分配該對象實例的記憶體空間,虛擬機棧分 ...
  • 1.目前PyOpenGL是用python2寫的,如果你使用的是python3需要自己修改PyOpenGL,我這裡使用的是python2.7 2.下載PyOpenGLhttps://pypi.org/project/PyOpenGL/3.1.0/#modal-close,下載對應系統版本的就可以 3. ...
  • 一、 例子:我們對傳參是有要求的必須傳入一個元組,否則報錯 二、 二、threading的使用 直接利用threading.Thread生成Thread的實例 格式: t= threading.Thread(target=函數體,args=(,))#參數args要傳遞元組 ​t.start()#啟動 ...
  • 1 字元串、數組、集合的轉換 定義字元串數組 String[] strArr 1.1 字元串數組轉集合 1.2 字元串集合轉數組 1.3 字元串集合轉逗號分隔的字元串 1.4 逗號分隔的字元串轉字元串集合 1.5 對象集合轉 Map 定義對象 Person 定義對象 Person 的集合 List ...
  • 限流演算法 計數器限流 固定視窗 滑動視窗 桶限流 令牌桶 漏桶 計數器 計數器限流可以分為: 固定視窗 滑動視窗 固定視窗 固定視窗計數器限流簡單明瞭,就是限制單位之間內的請求數,比如設置QPS為10,那麼從一開始的請求進入就計數,每次計數前判斷是否到10,到達就拒絕請求,並保證這個計數周期是1秒, ...
  • 一般我們不把資料庫的配置信息寫死在代碼中。 寫好代碼後,編譯、調試,成功後只把輸出目錄中的東西(jar包、.class文件、資源文件等)拷貝到伺服器上,由運維來管理。伺服器上是沒有源文件的(.java文件),我們我們把資料庫的配置信息寫死在代碼中,運維就不能修改資料庫的配置了,如果要換伺服器、要換數 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...