QT項目實戰 --- 串口調試助手
目錄
2、使用HM NIS Edit編輯器與NSIS編譯器更深層次打包
一、前言
給大家安利一款自己編寫的串口調試助手小軟件,使用QT5.5編寫,在windows下可正常使用,Linux環境下沒測試過,可能會出現亂碼,因為windows環境下的字符編碼是ANSI(在中文系統中ANSI就是GBK編碼),而Linux環境下字符編碼是UTF-8,調試助手中發送和接收的數據也都是按照GBK編碼轉換的。比如:
字符 | GBK編碼 | Unicode編碼 | UTF-8 |
"123學習" | 31 32 33 D1 A7 CF B0 | 31 32 33 5B 66 4E 60 | 31 32 33 E5 AD A6 E4 B9 A0 |
1、關于字符集編碼的延伸閱讀
6、QT字符編碼
2、關于字符編碼幾點的總結
1、字符就是一堆文字符號,每個國家都會有自己的語言文字,這些字符在計算機中怎么存儲呢?計算機中都是以01二進制存儲的,把這些字符轉成其對應且唯一的二進制碼不就行了。也就出現了各種編碼,比如英文的ASCII、中文的GDB編碼、日文的Shift-JIS編碼等等
2、ASCII碼:上個世紀60年代, 美國制定了一套字符編碼, 對英語字符與二進制位之間的關系, 做了統一規定,這被稱為ASCII碼,ASCII碼一共規定了128個字符的編碼。只占用了一個字節的后面7位, 最前面的1位統一規定為0
3、GBK碼:英語用128個符號編碼就夠了, 但是用來表示其他語言, 128個符號是不夠的,于是就使用兩個字節表示一個漢字, 所以理論上最多可以表示256x256=65536個符號
4、Unicode:世界上存在著多種編碼方式, 同一個二進制數字可以被解釋成不同的符號,要想打開一個文本文件, 就必須知道它的編碼方式, 否則用錯誤的編碼方式解讀, 就會出現亂碼。為了解決不統一的問題,有個國際組織就出來制定了包含世界上所有語言字符的編碼,這就是Unicode編碼。Unicode通常用兩個字節表示一個字符,原有的英文編碼從單字節變成雙字節,只需要把高字節全部填為0就可以。但是 Unicode只是一個符號集, 它只規定了符號的二進制代碼, 卻沒有規定這個二進制代碼應該如何存儲,如果用Unicode來表示1字節的ASCII優點浪費內存,而且也出現了不同存儲方式的Unicode
5、UTF-8編碼 :UTF-8就是在互聯網上使用最廣的一種unicode的實現方式. 其他實現方式還包括UTF-16和UTF-32。UTF-8最大的一個特點, 就是它是一種變長的編碼方式. 它可以使用1~6個字節表示一個符號, 根據不同的符號而變化字節長度.
二、功能與效果
1、效果
廢話不多說,先看效果
2、功能
1、記錄和保存串口的配置信息,便于下次打開時直接使用上次的配置
2、保存串口接收區的數據(可以是串口接收的的也可以是串口發送的)
3、一鍵清除接收窗口和發送窗口的數據
4、接收時,可以選擇16進制顯示還是字符顯示,可以選擇顯示當前的時間和發送的數據
5、發送時,可以選擇定時發送以及發送新行,可以發送文件數據。需要注意的是,選擇或不選擇16進制發送只是在發送區字符顯示的切換,發送的數據都是ANSI編碼的字節數據;勾選16進制時就將字符轉成ANSI編碼(這里是GBK編碼)顯示,不勾選16進制就顯示字符或是將16進制數據根據ANSI編碼轉成字符
6、可以顯示當前的串口狀態、發送的字節數、接收的字節數、當前的時間
三、實現過程
1、創建QMainWindow窗口與UI設計
創建后在 .pro 工程管理文件中添加 QT += serialport,這樣才能使用串口
2、代碼實現
源碼連接:https://github.com/denghengli/qt_study/tree/master/17_SerialPort
劃重點:
1、信號和槽的關聯方式
方法一:
0)如果是自定義的信號,需要在.h中聲明
1)在.h中聲明槽函數
2)在.cpp中實現槽函數
3)使用connect將信號和槽函數進行連接:
QObject::connect(ui->pushbutton,SIGNAL( clicked() ),this,SLOT( on_pushBuuton_clicked() );
方法二:
在.ui文件中,右擊按鈕,選擇''go to slot''選項,選擇信號"clicked",單機確定按鈕。系統自動生成槽函數聲明和定義,并建立內部映射。只需在槽函數體內編寫槽函數體內編寫槽函數的功能即可,添加語句如方法一中的步驟2.
方法三:
在.ui界面,選擇"改變信號/槽"選項,單擊"+"添加新的槽函數,確定完成槽函數的添加,最后重復方法一中的步驟1和步驟2完成槽函數聲明和定義.
2、文件發送和文件保存
通過QFileDialog類提供的文件對話框,來選擇要發送的文件和新建保存的文件
openfile_path = QFileDialog::getOpenFileName(this, "打開文件", "", "Text File(*.txt)");
savefile_path = QFileDialog::getSaveFileName(this,"另存為", savefile_path, "Text File(*.txt)");
3、配置信息的保存
每一次在配置完串口、波特率、停止位等后,打開串口時,通過QSettings類將這些配置信息以key-value的形式保存到預先規定的文件中;在每次打開軟件時也先讀取這個配置文件的數據,再設置串口
//創建ini配置文件
void SerialPort::configiniInit()
{
iniPath = new QDir;
iniFilename = iniPath->currentPath() + "/SerialPort.ini";
//構造一個QSettings對象,用于訪問存儲在名為iniFilename的文件中的設置。如果文件不存在,就創建它
configini = new QSettings(iniFilename, QSettings::IniFormat);
}
//讀取ini配置文件,設置下拉框的項目
void SerialPort::configiniRead()
{
configini->beginGroup("SETUP");
int i_port = configini->value("COM").toInt();
int i_baudrate = configini->value("baudrate").toInt();
int i_databit = configini->value("databit").toInt();
int i_checkbit = configini->value("checkbit").toInt();
int i_stopbit = configini->value("stopbit").toInt();
configini->endGroup();
ui->CB_port->setCurrentIndex(i_port);
ui->CB_baudrate->setCurrentIndex(i_baudrate);
ui->CB_databit->setCurrentIndex(i_databit);
ui->CB_checkbit->setCurrentIndex(i_checkbit);
ui->CB_stopbit->setCurrentIndex(i_stopbit);
}
//寫ini配置文件,將下拉框的項目索引寫入ini文件
void SerialPort::configiniWrite()
{
configini->beginGroup("SETUP");
configini->setValue("COM", ui->CB_port->currentIndex());
configini->setValue("baudrate", ui->CB_baudrate->currentIndex());
configini->setValue("databit", ui->CB_databit->currentIndex());
configini->setValue("checkbit", ui->CB_checkbit->currentIndex());
configini->setValue("stopbit", ui->CB_stopbit->currentIndex());
configini->endGroup();
}
4、字符與16進制編碼字符的互相轉換
不要弄混了,是字符與ANSI(這里是GBK)16進制編碼字符的互相轉換;
例如:“123學習” <----> "31 32 33 D1 A7 CF B0"
原因是,textEdit控件顯示的是QString字符,在顯示時需要在字符和16進制之間切換。
“123學習” ----> "31 32 33 D1 A7 CF B0" 步驟:
//1、獲取發送數據 QString = "123學習"
QString sendstr = ui->textEdit_tx->toPlainText();
//2、"123學習" --> GBK編碼:31 32 33 D1 A7 CF B0
QByteArray sendarray = sendstr.toLocal8Bit();//"123學習"在QT中是UTF8編碼的,所以這里需要使用toLocal8Bit轉成Winds中的GBK編碼
//3、GBK編碼:31 32 33 D1 A7 CF B0 --> GBK編碼字符:"31 32 33 D1 A7 CF B0"
QDataStream out(&sendarray,QIODevice::ReadWrite); //將字節數組讀入
while(!out.atEnd())
{
qint8 outChar = 0;
out>>outChar; //每字節填充一次,直到結束
QString str = QString("%1").arg(outChar&0xFF,2,16,QLatin1Char('0'));
str = str.toUpper();
ui->textEdit_tx->insertPlainText(str + " ");//在當前光標處插入文本
//返回表示當前可見游標的QTextCursor副本。對返回游標的更改不會影響QTextEdit的游標;使用setTextCursor()更新可見的游標
QTextCursor cursor = ui->textEdit_tx->textCursor();
cursor.movePosition(QTextCursor::End);//將光標移動到文檔的最后
ui->textEdit_tx->setTextCursor(cursor);//更新光標
}
"31 32 33 D1 A7 CF B0" ----> “123學習” 步驟:
//1、獲取發送數據 QString = "31 32 33 D1 A7 CF B0"
QString sendstr = ui->textEdit_tx->toPlainText();
QByteArray sendarray;
//2、GBK編碼字符:"31 32 33 D1 A7 CF B0" --> GBK編碼:31 32 33 D1 A7 CF B0
QStringtoHex(sendarray, sendstr);
//3、GBK編碼:31 32 33 D1 A7 CF B0 --> Unicode編碼 --> "123學習"
QString str1 = QString::fromLocal8Bit(sendarray);//實現了從本地字符集GBK到Unicode的轉換,解決中文顯示亂碼問題
ui->textEdit_tx->setText(str1);
可以看到 QStringtoHex(QByteArray& sendData,QString str)函數比較關鍵,但是實現起來也比較簡單
char SerialPort::ConvertHexChar(char c)
{
if(c>='a'&&c<='f'){
return c-'a'+10;
}
else if(c>='A'&&c<='F'){
return c-'A'+10;
}
else if(c>='0'&&c<='9'){
return c-'0';
}
else{
return -1;
}
}
//"31 32 33 D1 A7 CF B0" --> 31 32 33 D1 A7 CF B0
void SerialPort::QStringtoHex(QByteArray& sendData,QString str)
{
char hstr,lstr,hdata,ldata;
int len = str.length();
int sendnum = 0;
QByteArray temp;
temp.resize(len/2);//設置大小,len/2會大于實際16進制字符
for(int i=0;i<len;)
{
//QString轉QByteArray的方法,Latin1代表ASCII。'3' --> 3
hstr = str[i].toLatin1();
if(hstr == ' '){
++i; continue;
}
if(++i >= len) break;
lstr = str[i].toLatin1();
hdata = ConvertHexChar(hstr);
ldata = ConvertHexChar(lstr);
if(-1 == hdata || -1 == ldata)
break;
++i;
temp[sendnum] = hdata<<4|ldata;
sendnum++;
}
sendData.reserve(sendnum);//重新調整大小
sendData = temp.left(sendnum);//返回一個 字節數組,其中包含這個字節數組最左邊的len字節。去掉多余字符
}
3、工程打包發布
1、使用QT自帶的windeployqt.exe打包
1、選擇 release,構建工程
2、將 .exe文件拷貝到任意路徑下,將其進行打包,這樣在任意一臺沒有安裝QT環境的電腦也可以運行,打包前首先要確保QT的安裝目錄下有 windeployqt.exe
3、打開終端,進入到.exe目錄下(快捷方式:在文件夾中,點擊空白處,shift+右鍵,選擇“在此處打開窗口”),輸入 windeployqt.exe 文件
4、生成成功后,會在當前目錄下生成一些文件,將此文件夾拷貝到任意沒有QT環境的電腦上也能運行
2、使用HM NIS Edit編輯器與NSIS編譯器更深層次打包
1、先使用QT自帶的windeployqt.exe打包,生成可執行文件和需要的動態庫
2、下載安裝 NSIS 和 NIS Edit 這兩個軟件
3、根據 NIS Edit安裝向導的使用 步驟,將windeployqt.exe 打包后的文件再打包生成一個 Setup.exe 的安裝向導文件;使用NIS EDIT安裝時,有個需要注意的地方,在選擇應用程序的文件時,要選擇需要打包的文件夾
完成后就可以通過這個Setup.exe來安裝并使用串口調試助手了。在安裝 Setup.exe 的時候根據提示下一步下一步就可以了。這樣逼格是不是都提高了 哈哈
四、功能測試
1、下載一個虛擬串口的工具,我下載的是 VSDP ,當然其他的也行,只要能在本地虛擬出串口就行,如下圖,COM1和COM2就可以互聯了;"Add pair "添加新的虛擬串口
2、用serialport打開COM2,隨便用一個串口調試助手(我這里用的XCOM)打開COM1,測試互相發送數據都是ok的
智能推薦
QT實現串口調試助手(六):頁面布局
工程源碼:https://github.com/zhangfls/QT_UartAnalysisTool 上一篇: INI文件存取串口信息 之前沒有設置頁面布局,當窗口進行放大縮小時,組件的位置還是保持原樣,這樣很不實用。所以要調整一下頁面和組件布局 QT幾種常見的布局: 下面就用這些布局調整一下組件的位置排布。 1、添加horizontalLayout水平布局,將頁面...
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...
猜你喜歡
Linux C系統編程-線程互斥鎖(四)
互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...
統計學習方法 - 樸素貝葉斯
引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...
styled-components —— React 中的 CSS 最佳實踐
https://zhuanlan.zhihu.com/p/29344146 Styled-components 是目前 React 樣式方案中最受關注的一種,它既具備了 css-in-js 的模塊化與參數化優點,又完全使用CSS的書寫習慣,不會引起額外的學習成本。本文是 styled-components 作者之一 Max Stoiber 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...