基于winform的串口調試助手

目錄

一、串口助手界面設計

1.1 串口配置

1.2 接收配置

1.3 發送配置

1.4 接收窗口和發送窗口

1.5 狀態顯示窗口

1.6 串口通訊控件

二、程序編寫

2.1 端口號自動識別并顯示在端口號下拉框

功能說明:

2.2? 波特率下拉框顯示

2.3 數據位下拉框顯示

2.4 校驗位下拉框顯示

2.5 停止位下拉框顯示

2.6 停止位列表數字與serialport1使用的枚舉類型對應

2.7 選擇的串口名稱、波特率、數據位、校驗位、停止位參數賦值給serialport1對應的變量

2.8 編寫串口打開按鈕的點擊事件

2.9 串口數據發送程序編寫

2.10 串口數據接收程序編寫


一、串口助手界面設計

1.1 串口配置

采用groupbox控件,其中包括了串口配置、波特率、數據位、校驗位、停止位、RTS、DTR和打開串口控件。

① 串口配置、波特率、數據位、校驗位、停止位:combobox控件和對應文字描述的label控件

② RTS、DTR:checkbox控件

③ 打開串口:最熟悉的button控件 哈哈哈

1.2 接收配置

同樣采用groupbox控件,支持清空數據、暫停接收、保存數據等功能;可選擇十六進制顯示,便于查看原始數據格式;可指定保存路徑,便于數據。

① 自動清空、16進制:checkbox控件

② 手動清空、暫停、保存數據和選擇路徑:button控件

③ 文件保存路徑:textbox控件

1.3 發送配置

同樣采用 GroupBox 控件,支持手動輸入數據發送、文件發送以及自動循環發送功能;可選擇十六進制格式發送,適用于不同通信協議的調試需求;可設置發送時間間隔,滿足周期性發送場景。

① 自動發送、16進制:CheckBox 控件

② 手動發送、清除數據、發送文件和選擇路徑:Button 控件

③ 文件路徑選擇及發送周期設定:TextBox 控件

1.4 接收窗口和發送窗口

接收窗口和發送窗口采用的是richtextbox控件

1.5 狀態顯示窗口

狀態接收采用的是statustrip控件,主要包括了狀態、接收數量、發送數量和清空計數功能。

1.6 串口通訊控件

使用serialport控件進行串口通訊,本次編寫的串口軟件主要是依托于serialport控件及其對應的類,本次串口軟件中serialport空間名字名為serialport1,后續程序中都是使用該名稱進行編寫程序。

二、程序編寫

2.1 端口號自動識別并顯示在端口號下拉框

private void save_btn_Load(object sender, EventArgs e)
{// 將電腦上的串口資源加載到 port_cbb(端口選擇下拉框)中this.port_cbb.Items.AddRange(SerialPort.GetPortNames());// 初始化發送和接收區域的提示文字this.sent_rtb.Text = "我是發送區域";this.receive_rtb.Text = "我是接收區域";
}

其中的serialport是system.IO.ports命名空間下的serialport類的一個實例對象,在串口軟件頁面加載事件中進行創建的實例對象。

?

功能說明:
  • 🔍 自動識別串口:通過 SerialPort.GetPortNames() 獲取當前計算機所有可用串口號,并添加到 ComboBox 控件中,供用戶選擇,提升了使用的便捷性。

  • ?? 區域提示信息:在發送區(sent_rtb)和接收區(receive_rtb)初始化時分別添加默認提示文字,讓用戶一目了然地了解每個區域的功能。

2.2? 波特率下拉框顯示

直接在波特率下拉框控件中的item屬性中設置常用的波特率數值:19200、9600、4800、2400,程序運行以后直接可以根據通訊要求進行選擇對應波特率。

2.3 數據位下拉框顯示

同上述②,直接在控件的item屬性中設置常用的數據長度:5、6、7、8

2.4 校驗位下拉框顯示

同上述③,直接控件的item屬性設置常用的校驗位類型:Odd、Even、None、Mark、Space

2.5 停止位下拉框顯示

同上述④,直接在控件的item屬性中設置常用的停止位類型:1、2、1.5

注意事項:當數據為6、7、8時,停止位只能配置成1或者2;當數據位為5時,停止位只能設置成1或者1.5位。另外,serialport1中使用的停止位是枚舉類型,需要將停止位列表中的數字于serialport1中使用的停止位枚舉類型進行一一對應。

2.6 停止位列表數字與serialport1使用的枚舉類型對應

停止位下拉列表中的數字實際是字符串,serialport1的停止位設置使用“serialport.stopbits”枚舉類型進行設置,將字符串和stopbits枚舉中的選項進行對應,具體如下所示。

switch (stopbit_cbb.SelectedItem.ToString()){case "1.5":this.serialPort1.StopBits = StopBits.OnePointFive;break;case "1":this.serialPort1.StopBits = StopBits.One;break;case "2":this.serialPort1.StopBits = StopBits.Two;break;}

2.7 選擇的串口名稱、波特率、數據位、校驗位、停止位參數賦值給serialport1對應的變量

this.serialPort1.PortName = this.port_cbb.SelectedItem.ToString();this.serialPort1.BaudRate = Convert.ToInt32(baud_cbb.SelectedItem);this.serialPort1.DataBits = Convert.ToInt32(databit_cbb.SelectedItem);this.serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), checkbit_cbb.Text.ToString());serialPort1.Encoding = Encoding.UTF8;

?其中,serialport.encoding是編碼格式,本次的串口助手中使用的utf-8,用于后續串口數據的發送和接收;由于控件中item參數默認的數據類型是字符串,需要將字符串轉換成serialport需要的數據,涉及字符串轉數字,字符串轉枚舉。校驗位參數是枚舉類型,其在serialport1中可設置的值如下所示:

2.8 編寫串口打開按鈕的點擊事件

基本流程如下所示

開始|v
[點擊“打開串口”按鈕]|v
{openport_btnisopen == false?}| 是v
[配置串口參數]- 串口號(PortName)- 波特率(BaudRate)- 數據位(DataBits)- 校驗位(Parity)- 停止位(StopBits,根據選擇設置)- 編碼格式(UTF-8)|v
[打開串口 serialPort1.Open()]|v
{串口是否成功打開? serialPort1.IsOpen == true}| 是v
[按鈕背景設為綠色]
[按鈕文字設為“關閉串口”]
[設置 openport_btnisopen = true]|v
結束{openport_btnisopen == false?}| 否v
[關閉串口 serialPort1.Close()]
[按鈕背景設為灰色]
[按鈕文字設為“打開串口”]
[設置 openport_btnisopen = false]|v
結束

注意:其中的openport_btnisopen時一個全局變量,在串口軟件界面初次加載的時候賦值為false。

打開串口按鈕事件具體代碼如下所示:

private void openport_btn_Click(object sender, EventArgs e){try{if (openport_btnisopen==false){//串口名稱、波特率、數據位、校驗位、停止位參數設置this.serialPort1.PortName = this.port_cbb.SelectedItem.ToString();this.serialPort1.BaudRate = Convert.ToInt32(baud_cbb.SelectedItem);this.serialPort1.DataBits = Convert.ToInt32(databit_cbb.SelectedItem);this.serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), checkbit_cbb.Text.ToString());serialPort1.Encoding = Encoding.UTF8;//當數據位為6、7、8位時,停止位只能配置成1或2位;同樣當數據位為5位時,停止位只能為1或1.5位switch (stopbit_cbb.SelectedItem.ToString()){case "1.5":this.serialPort1.StopBits = StopBits.OnePointFive;break;case "1":this.serialPort1.StopBits = StopBits.One;break;case "2":this.serialPort1.StopBits = StopBits.Two;break;}//打開端口this.serialPort1.Open();if (this.serialPort1.IsOpen ==true){this.openport_btn.BackColor = Color.Green;this.openport_btn.Text = "關閉串口";}openport_btnisopen = true;}else{this.serialPort1.Close();this.openport_btn.BackColor = Color.Gainsboro;this.openport_btn.Text = "打開串口";openport_btnisopen = false;}           //關閉端口}catch (Exception xc){}}

2.9 串口數據發送程序編寫

在發送數據之前,需要判斷發送框內的數據是否為空和串口通訊是否打開這兩個條件。如果條件滿足,使用“encoding.Getbytes”函數將發送框內的數據換成字節數據,使用serialport.write函數將轉換得到的字節數據發送給對方。

注意:本次串口助手軟件中沒有補充不滿足條件的執行代碼,小伙伴可以根據自己的要求進行補充完善。

private void hand_send_btn_Click(object sender, EventArgs e){if (sent_rtb.Text !=null && this.serialPort1.IsOpen){Encoding Chinese = System.Text.Encoding.UTF8;//定義一個可以進行中文編碼的變量byte[] writeBytes = Chinese.GetBytes(sent_rtb.Text);this.serialPort1.Write(writeBytes,0, writeBytes.Length);//this.serialPort1.Write(writeBytes,0, writeBytes.Length);}}

2.10 串口數據接收程序編寫

這個是B站上up主編寫的數據接收程序,使用的編碼格式是GB2312,首先在串口數據接收事件中聲明了個字節數組,字節數組長度是串口緩存區中可以讀取字節的數目,使用串口的read函數,將串口緩存區中的可讀字節數據讀取并存到字節數組中。同時將字節數組數據存儲到全局的列表recivebuffer中,使用invoke將讀取的數據在UI界面里的窗口顯示區域進行顯示(涉及到UI線程和非UI線程的問題,有興趣的小伙伴可以查點資料看看)。

2.10.1 VSPD軟件

這里介紹一個虛擬串口軟件Virtual Serial Port Driver,它是 Eltima Software 出品的一款 虛擬串口工具,可以在系統中創建成對的虛擬串口(如 COM3 <-> COM4),廣泛用于串口通信調試、設備模擬和串口軟件開發中。

具體原理如下:

1.串口通訊調試

? 開發者可用它來模擬串口設備之間的通信,實現無需真實硬件的調試環境。

  • 例如:開發一款串口通信的軟件,但沒有真實的串口設備,就可以用 COM3 <-> COM4 虛擬一對串口,一端運行你的軟件,另一端用串口助手發送測試數據。


2.串口數據轉發、轉接協議調試

? 可用于協議橋接、數據透傳、協議中間件調試

  • 比如:

    • A 程序向 COM5 發數據;

    • B 程序從 COM6 接收;

    • COM5 和 COM6 通過 VSPD 連接;

    • 就可以驗證 A 和 B 之間串口協議是否兼容。

具體使用教程可以參考博客:

VSPD工具 - Virtual Serial Port Driver v6.9 激活教程&使用教程 - Citrusliu - 博客園

具體下載鏈接(網上很多資源):

https://gitcode.com/open-source-toolkit/29e06/?utm_source=tools_gitcode&index=top&type=cardhttps://gitcode.com/open-source-toolkit/29e06/?utm_source=tools_gitcode&index=top&type=card

2.10.2 串口通訊實驗

根據上述截圖中的串口數據接收代碼,自己進行了一定的改寫,使得程序能夠滿足自己串口軟件的使用。具體程序如下所示:

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e){//如果暫停按鈕被按下則停止接收數據if (receiveisopen == false){return;}if (serialPort1.BytesToRead==0){return;}byte[] z = new byte[this.serialPort1.BytesToRead];this.serialPort1.Read(z,0,z.Length);datahuanchun.AddRange(z);this.Invoke(new EventHandler(delegate{if (hex_receive_ckb.Checked == true){//編寫數據采用16進制進行顯示}else{//編寫數據采用字符串進行顯示if (serialPort1.BytesToRead == 0){//判斷串口緩存區沒有可以在讀的字節數據string xx = Encoding.UTF8.GetString(datahuanchun.ToArray());receive_rtb.AppendText(xx);//接收完成后清空datahaunchundatahuanchun.Clear();}}}));

具體實驗結果如下圖所示:

這個問題如果你用單步調試可能查不出問題,因為單步調試執行一步,中間存在間隔時間,串口傳輸的線程可以在間隔時間內將全部數據發送給你,當你解碼的時候,數據往往是一段完整的數據。

注意事項:在使用串口方式進行數據收發過程中,需要知道串口數據并不是一次性全部發送,它可能是分多批次地給你發送。這個結果就可能導致中文轉碼時發生亂碼問題,為什么這么說呢,聽我細細道來:

(1)單個字母和數字對應一個字節

(2)一個中文(UTF8編碼)對應三個字節;一個中文(GB2312編碼)對應兩個字節

舉個例子:

舉個例子:

假設你串口接收 "你" 字(UTF-8編碼為 E4 BD A0):

  • 第一次讀取:收到 E4 BD(2個字節,還差1個字節)

  • 第二次讀取:收到 A0

程序連續執行時(正常運行):
  • 程序執行速度快,串口緩沖區數據還沒完全到齊你就開始處理

  • 比如 UTF-8 中文“你”應為 E4 BD A0,但你先只收到 E4 BD,立刻嘗試解碼就會報錯或亂碼。

2.10.3 中文亂碼解決方法

以下是程序編寫流程圖:需要用到lock鎖

開始|v
[進入 serialPort1_DataReceived 事件]|v
{是否按下“暫停接收”按鈕? (receiveisopen == false)}| 是v
[直接 return,結束接收]|v
結束|否v
{串口接收緩存是否為空? (BytesToRead == 0)}| 是v
[直接 return,結束接收]|否v
[定義接收字節數組 z,并讀取數據到 z]|v
[將讀取數據加入 datahuanchun 緩存(加鎖 lock)]|v
[Invoke 主線程處理接收顯示邏輯]|v
{是否勾選“16進制顯示”? (hex_receive_ckb.Checked == true)}| 是v
[此處未寫實現邏輯,可擴展為 hex 格式顯示]|否v
[進入文本顯示分支(加鎖 datahuanchun)]|v[UTF8 解碼緩存數據 → charBuffer]|v[將解碼結果追加到接收顯示區 receive_rtb]|v[清空 datahuanchun 緩存]|v[更新接收數據統計 senddata_num + data長度]|v[更新狀態欄 toolStripStatusLabel4]|v
結束

等后面串口軟件寫好后,再上傳下一部分內容

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/75751.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/75751.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/75751.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Docker基礎2

如需轉載&#xff0c;標記出處 本次我們將下載一個 Docker 鏡像&#xff0c;從鏡像中啟動容器 上一章&#xff0c;安裝 Docker 時&#xff0c;獲得兩個主要組件&#xff1a; Docker 客戶端 Docker 守護進程&#xff08;有時稱為“服務器”或“引擎”&#xff09; 守護進程實…

Rocketmq2

一、生產者端防丟失 1. 發送方式選擇 同步發送&#xff1a;使用 send() 方法&#xff0c;等待 Broker 確認響應&#xff08;SendResult&#xff09;&#xff0c;確保消息已成功發送。異步發送&#xff1a;使用 sendAsync() 方法并設置回調函數&#xff0c;處理發送成功 / 失敗…

RabbitMQ詳解,RabbitMQ是什么?架構是怎樣的?

目錄 一,RabbitMQ是什么? 二,RabbitMQ架構 2.1 首先我們來看下RabbitMQ里面的心概念Queue是什么? 2.2 交換器Exchange 2.3 RabbitMQ是什么? 2.4 重點看下優先級隊列是什么? 三,RabbitMQ集群 3.1 普通集群模式 3.2 鏡像隊列集群 一,RabbitMQ是什么? 假設我們程序…

【一步步開發AI運動APP】六、運動計時計數能調用

之前我們為您分享了【一步步開發AI運動小程序】開發系列博文&#xff0c;通過該系列博文&#xff0c;很多開發者開發出了很多精美的AI健身、線上運動賽事、AI學生體測、美體、康復鍛煉等應用場景的AI運動小程序&#xff1b;為了幫助開發者繼續深耕AI運動領域市場&#xff0c;今…

MySQL——DQL的多表查詢

一、交叉連接 標準語法&#xff1a;select * from 表1 cross join 表2 where 表1.公共列 表2.公共列; 簡單語法&#xff1a;select * from 表1 , 表2 where 表1.公共列 表2.公共列; 公共列&#xff1a;兩張表具有相同含義的列&#xff0c;不是列名一樣。 …

【Linux內核】如何更加優雅閱讀Linux內核源碼(vscode)

1. 前言 因為已經習慣在Ubuntu下進行嵌入式工作開發&#xff0c;但Linux源碼在Source Insight下進行閱讀&#xff0c;一直很苦惱Linux/Windows來回切換的開發方式&#xff0c;當前發現可以通過 vscode clangd(擴展組件) 方式進行更好的內核源碼閱讀。 2. 環境 操作系統&…

21.OpenCV獲取圖像輪廓信息

OpenCV獲取圖像輪廓信息 在計算機視覺領域&#xff0c;識別和分析圖像中的對象形狀是一項基本任務。OpenCV 庫提供了一個強大的工具——輪廓檢測&#xff08;Contour Detection&#xff09;&#xff0c;它能夠幫助我們精確地定位對象的邊界。這篇博文將帶你入門 OpenCV 的輪廓…

LETTERS(DFS)

【題目描述】 給出一個rowcolrowcol的大寫字母矩陣&#xff0c;一開始的位置為左上角&#xff0c;你可以向上下左右四個方向移動&#xff0c;并且不能移向曾經經過的字母。問最多可以經過幾個字母。 【輸入】 第一行&#xff0c;輸入字母矩陣行數RR和列數SS&#xff0c;1≤R,S≤…

Day2-2:前端項目uniapp壁紙實戰

再在wallpaper新建一個目錄components 在components下新建組件common-title 記得點擊創建同名目錄 在index加 <view class"select"><common-title></common-title></view> 圖片換了下&#xff0c;原來的有點丑&#xff0c;圖片可按自己喜歡…

其他 vector 操作詳解(四十)

介紹 除去向 vector 添加元素&#xff08;如 push_back&#xff09;之外&#xff0c;vector 還提供了許多其他操作&#xff0c;這些操作大多與 string 的操作類似。通過掌握這些操作&#xff0c;我們可以方便地查詢、修改和比較 vector 中的元素&#xff0c;從而構建靈活、高效…

【Leetcode 每日一題】368. 最大整除子集

問題背景 給你一個由 無重復 正整數組成的集合 n u m s nums nums&#xff0c;請你找出并返回其中最大的整除子集 a n s w e r answer answer&#xff0c;子集中每一元素對 ( a n s w e r [ i ] , a n s w e r [ j ] ) (answer[i], answer[j]) (answer[i],answer[j]) 都應當…

python基礎-13-處理excel電子表格

文章目錄 【README】【13】處理Excel電子表格【13.1】Excel文檔【13.2】安裝openpyxl模塊【13.3】讀取Excel文檔【13.3.1】使用openpyxl模塊打開excel文檔【13.3.2】從工作簿取得工作表【13.3.3】從工作表sheet獲取單元格cell【13.3.5】從表中獲取行和列【13.3.6】工作簿、工作…

ABS函數c++

簡介&#xff1a; abs 函數用于計算一個數的絕對值&#xff0c;在 C 中它繼承自 C 語言的標準庫&#xff0c;其歷史可以追溯到早期的 C 語言發展歷程&#xff0c;以下是詳細介紹&#xff1a; 早期編程語言的需求 在計算機編程的早期階段&#xff0c;處理數學運算就是一項基本…

閉環SOTA!北航DiffAD:基于擴散模型實現端到端自動駕駛「多任務閉環統一」

端到端自動駕駛目前是有望實現完全自動駕駛的一條有前景的途徑。然而&#xff0c;現有的端到端自動駕駛系統通常采用主干網絡與多任務頭結合的方式&#xff0c;但是它們存在任務協調和系統復雜度高的問題。為此&#xff0c;本文提出了DiffAD&#xff0c;它統一了各種駕駛目標并…

整車CAN網絡和CANoe

車載網絡中主要包含有Can網絡,Lin網絡,FlexRay,Most,以太網。 500kbps:500波特率,表示的數據傳輸的速度。表示的是最大的網速傳輸速度。也就是每秒 500kb BodyCan車身Can InfoCan娛樂信息Can 車身CAN主要連接的是ESB電動安全帶 ADB自適應遠光燈等 PTCan動力Can 底盤Can

實戰設計模式之迭代器模式

概述 與上一篇介紹的解釋器模式一樣&#xff0c;迭代器模式也是一種行為設計模式。它提供了一種方法來順序訪問一個聚合對象中的各個元素&#xff0c;而無需暴露該對象的內部表示。簡而言之&#xff0c;迭代器模式允許我們遍歷集合數據結構中的元素&#xff0c;而不必了解這些集…

JVM 垃圾回收器是如何判斷一個對象是否要回收?

JVM 垃圾回收器&#xff08;Garbage Collector&#xff09;需要判斷哪些對象是“垃圾”&#xff0c;即不再被程序使用的對象&#xff0c;以便回收它們占用的內存。JVM 主要使用以下兩種方法來判斷對象是否是垃圾&#xff1a; 1. 引用計數算法 (Reference Counting): 原理&…

kali——httrack

目錄 前言 使用教程 前言 HTTrack 是一款運行于 Kali Linux 系統中的開源網站鏡像工具&#xff0c;它能將網站的頁面、圖片、鏈接等資源完整地下載到本地&#xff0c;構建出一個和原網站結構相似的離線副本。 使用教程 apt install httrack //安裝httrack工具 httrac…

kotlin函數類型

一 函數類型定義 1 定義 函數類型就是 (Int, Int) -> Int 函數類型其實就是將函數的 “參數類型” 和 “返回值類型” 抽象出來 2 示例 &#xff1a; (Int, Int) -> Int 表示接收兩個 Int 參數并返回 Int 的函數類型&#xff1b; (String) -> Unit 表示接收 Strin…

C# Winform 入門(9)之如何封裝并調用dll

封裝dll 首先創建 .Net平臺 類庫 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace _09.Encapsulation_dll {public class Program{/// <summary>/// 求兩個double類型的數值的和/// &l…