c#:使用串口通訊實現數據的發送和接收

串口通訊(Serial Communication)是一種常見的硬件設備與計算機之間的數據傳輸方式,廣泛應用于工業控制、嵌入式系統、傳感器數據采集等領域。本文將詳細介紹如何使用C#實現基于串口通訊的數據發送和接收,并結合代碼示例解析其實現過程。

1. 概述

串口通訊的核心是System.IO.Ports.SerialPort類,它封裝了串口操作的底層細節,提供了簡單易用的接口。以下是串口通訊的基本流程:

1.初始化串口:設置串口參數(如波特率、數據位、停止位等)。

2.打開串口:通過SerialPort.Open方法打開串口。

3.發送數據:通過SerialPort.Write方法向串口發送數據。

4.接收數據:通過SerialPort.DataReceived事件異步接收數據。

5.處理數據:對接收到的數據進行解析和處理。

2. 關鍵技術點

2.1 SerialPort類

SerialPort是C#中用于實現串口通訊的核心類,提供了發送和接收數據的方法。

2.2 異步接收數據

通過SerialPort.DataReceived事件異步接收數據,避免阻塞主線程。

2.3 數據解析

接收到的數據通常是字節數組(byte[]),需要根據協議格式進行解析。

2.4 事件機制

通過事件機制將接收到的數據傳遞給其他模塊處理。

3. 代碼實現

以下是基于串口通訊實現數據發送和接收的代碼示例。

3.1 SerialPortHelper類
SerialPortHelper類負責初始化串口、發送數據、接收數據以及處理數據。

public class SerialPortHelper
{private SerialPort serialPort; // 串口對象private List<byte> _buffer = new List<byte>(); // 數據緩沖區/// <summary>/// 自定義串口消息接收事件/// </summary>public event ReceiveDataEventHandler ReceiveDataEvent;public SerialPortHelper(){serialPort = new SerialPort();}/// <summary>/// 獲取當前計算機所有的串行端口名/// </summary>public static string[] GetPortArray(){return SerialPort.GetPortNames(); // 獲取所有可用串口}/// <summary>/// 設置串口參數/// </summary>public void SetSerialPort(string portName, int baudrate, Parity parity, int databits, StopBits stopBits){serialPort.PortName = portName; // 端口名serialPort.BaudRate = baudrate; // 波特率serialPort.Parity = parity; // 奇偶校驗serialPort.DataBits = databits; // 數據位serialPort.StopBits = stopBits; // 停止位serialPort.DataReceived += ReceiveDataMethod; // 訂閱數據接收事件}/// <summary>/// 打開串口/// </summary>public void Open(){try{serialPort.Open(); // 打開串口}catch (Exception ex){Console.WriteLine("Error opening serial port: " + ex.Message);}}/// <summary>/// 關閉串口/// </summary>public void Close(){serialPort.Close(); // 關閉串口}/// <summary>/// 發送數據(字節數組)/// </summary>public void SendDataMethod(byte[] data){if (!serialPort.IsOpen){Open(); // 如果串口未打開,則先打開}serialPort.Write(data, 0, data.Length); // 發送數據}/// <summary>/// 發送數據(字符串)/// </summary>public void SendDataMethod(string data){if (!serialPort.IsOpen){Open(); // 如果串口未打開,則先打開}serialPort.Write(data); // 發送字符串}/// <summary>/// 數據接收事件處理方法/// </summary>private void ReceiveDataMethod(object sender, SerialDataReceivedEventArgs e){try{byte[] dataChunk = new byte[serialPort.BytesToRead]; // 讀取緩沖區中的數據serialPort.Read(dataChunk, 0, dataChunk.Length);_buffer.AddRange(dataChunk); // 將數據添加到緩沖區while (_buffer.Count >= 3) // 確保緩沖區中有足夠的數據{byte thirdByte = _buffer[1]; // 獲取第三個字節(功能碼)if (thirdByte == 0x03) // 功能碼0x03{if (_buffer.Count >= 19) // 檢查是否有完整的數據包{byte[] completePacket = _buffer.GetRange(0, 19).ToArray(); // 提取完整數據包TriggerReceiveDataEvent(completePacket); // 觸發接收事件_buffer.RemoveRange(0, 19); // 移除已處理的數據}else{break; // 數據不足,等待更多數據}}else if (thirdByte == 0x10 || thirdByte == 0x06) // 功能碼0x10或0x06{byte[] dataToProcess = _buffer.ToArray(); // 處理整個緩沖區TriggerReceiveDataEvent(dataToProcess); // 觸發接收事件_buffer.Clear(); // 清空緩沖區}else{_buffer.RemoveRange(0, 3); // 移除無法識別的數據}}}catch (Exception ex){Console.WriteLine("Error processing serial port data: " + ex.Message);}}/// <summary>/// 觸發接收數據事件/// </summary>private void TriggerReceiveDataEvent(byte[] data){if (ReceiveDataEvent != null){ReceiveDataEventArg arg = new ReceiveDataEventArg(data); // 創建事件參數ReceiveDataEvent.Invoke(this, arg); // 觸發事件}}
}

3.2 ReceiveDataEventArg類

ReceiveDataEventArg類用于封裝接收到的數據,并作為事件參數傳遞。

public class ReceiveDataEventArg : EventArgs
{public byte[] Data { get; set; } // 接收到的數據public ReceiveDataEventArg(byte[] data){Data = data; // 初始化數據}
}

3.3 主窗體(MainWindow)

主窗體負責初始化SerialPortHelper并處理接收到的數據。

public partial class MainWindow : Window
{private SerialPortHelper serialPortHelper;public MainWindow(){InitializeComponent();SettingComPorts(); // 初始化串口}private void SettingComPorts(){string portName = "COM8"; // 串口名稱int baudRate = 115200; // 波特率Parity parity = Parity.None; // 奇偶校驗int dataBits = 8; // 數據位StopBits stopBits = StopBits.One; // 停止位serialPortHelper = new SerialPortHelper();serialPortHelper.SetSerialPort(portName, baudRate, parity, dataBits, stopBits); // 設置串口參數serialPortHelper.Open(); // 打開串口serialPortHelper.ReceiveDataEvent += ReceiveDataEvent; // 訂閱接收數據事件}/// <summary>/// 接收數據事件處理方法/// </summary>private void ReceiveDataEvent(object sender, ReceiveDataEventArg e){byte[] receivedData = e.Data; // 獲取接收到的數據if (receivedData[1] == 0x03) // 功能碼0x03{int receiveDataLength = receivedData[2]; // 獲取有效數據長度byte[] receiveDataBuffer = new byte[receiveDataLength];Array.Copy(receivedData, 3, receiveDataBuffer, 0, receiveDataLength); // 提取有效數據ushort[] units = messageData.GetUnitsFromByteArray(receiveDataBuffer); // 解析數據if (units != null){List<ChannelData> channelDatas = databaseHelper.GetUUTInfo(units); // 獲取設備信息UpdateDeviceInfo(channelDatas); // 更新UI}}}
}

4. 數據傳遞流程詳解

4.1 初始化串口

在SettingComPorts方法中,設置串口參數并打開串口。

訂閱ReceiveDataEvent事件以接收數據。

4.2 發送數據

通過SendDataMethod方法向串口發送數據。

4.3 接收數據

串口接收到數據后,觸發ReceiveDataMethod方法。

將接收到的數據添加到緩沖區,并根據功能碼解析數據。

4.4 處理數據

在ReceiveDataEvent方法中,解析接收到的數據并更新UI。

5. 關鍵技術解析

5.1 異步接收數據

通過SerialPort.DataReceived事件異步接收數據,避免阻塞主線程。

5.2 數據解析

根據功能碼(如0x03、0x06)解析接收到的字節數組,提取有效數據。

5.3 事件機制

通過事件將接收到的數據傳遞給主窗體或其他模塊處理。

6. 總結

本文詳細介紹了如何使用C#實現基于串口通訊的數據發送和接收。通過SerialPort類,我們可以輕松實現串口通訊,并結合事件機制實現數據的傳遞和處理。串口通訊適用于硬件設備與計算機之間的數據傳輸,是工業控制和嵌入式系統開發中的重要技術。

希望這篇文章對您有所幫助!如果有任何問題,歡迎在評論區留言討論。

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

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

相關文章

k8s面經

最近面了幾場&#xff0c;k8s技能幾乎成了運維的必備品了。 容器一直pending可能的原因調度問題。容器的調度策略&#xff0c;比如標簽選擇、容忍度或者親和度&#xff0c;導致沒有合適的節點可供調度 資源問題&#xff0c;比如宿主機的CPU內存磁盤不足&#xff0c;或者要掛載…

網絡通信(傳輸層協議:TCP/IP ,UDP):

Socket是對網絡中不同主機上的應用進程之間進行雙向通信的端點的抽象。一個套接字就是網絡上進程通信的一端&#xff0c;提供了應用層進程利用網絡協議交換數據的機制。 網絡協議&#xff1a;一臺電腦的數據怎么傳遞給另一臺電腦&#xff0c;是由網絡協議來規定的 端口號&#…

DeepSeek進階應用(二):結合Kimi制作PPT(雙AI協作教程)

&#x1f31f;引言&#xff1a; DeepSeek作為國產AI大模型&#xff0c;以強大的邏輯推理和結構化內容生成能力著稱&#xff0c;擅長根據用戶需求生成PPT大綱或Markdown文本&#xff1b;Kimi的PPT助手則能解析結構化內容并套用模板快速生成美觀的PPT&#xff0c;兩者結合實現“內…

卷積神經網絡(知識點)

一、為了使特征圖變小&#xff1a; 由兩種方法&#xff1a;1.增大步長&#xff1a;卷積的時候不是一次一步&#xff0c;而是一次多步&#xff0c;類似一張圖片&#xff0c;在原來的像素基礎上&#xff0c;每隔一個取一個像素點。 其中S就是步長 注意&#xff1a;擴大步長不經…

考研系列-408真題計算機網絡篇(18-23)

寫在前面 此文章是本人在備考過程中408真題計算機網絡部分&#xff08;2018年-2023年&#xff09;的易錯題及相應的知識點整理&#xff0c;后期復習也常常用到&#xff0c;對于知識提煉歸納理解起到了很大的作用&#xff0c;分享出來希望幫助到大家~ # 2018 1.停止-等待協議的…

std::invoke詳解

基礎介紹 c17版本引入了std::invoke特性&#xff0c;這是一個通用的調用包裝器&#xff0c;可以統一調用&#xff1a; 普通函數成員函數函數對象Lambda表達式指向成員的指針 它的主要作用是提供一個統一的方式來調用各種可調用對象。 std::invoke依賴的頭文件&#xff1a;#…

使用 PaddleNLP 在 CPU(支持 AVX 指令)下跑通 llama2-7b或DeepSeek-r1:1.5b 模型(完成度80%)

原文&#xff1a;&#x1f6a3;?♂? 使用 PaddleNLP 在 CPU(支持 AVX 指令)下跑通 llama2-7b 模型 &#x1f6a3; — PaddleNLP 文檔 使用 PaddleNLP 在 CPU(支持 AVX 指令)下跑通 llama2-7b 模型 &#x1f6a3; PaddleNLP 在支持 AVX 指令的 CPU 上對 llama 系列模型進行了…

Kotlin高效實現 Android ViewPager2 頂部導航:動態配置與性能優化指南

高效實現&#xff1a;強調代碼的性能優化。Android ViewPager2&#xff1a;明確技術棧。頂部導航&#xff1a;核心功能點。動態配置與性能優化指南&#xff1a;突出動態配置的靈活性和性能優化的重點。 在 Android 開發中&#xff0c;使用 ViewPager2 實現高效的頂部導航&…

六種最新優化算法(TOC、MSO、AE、DOA、GOA、OX)求解多個無人機協同路徑規劃(可以自定義無人機數量及起始點),MATLAB代碼

一、算法簡介 &#xff08;一&#xff09;阿爾法進化&#xff08;Alpha Evolution&#xff0c;AE&#xff09;算法 阿爾法進化&#xff08;Alpha Evolution&#xff0c;AE&#xff09;算法是2024年提出的一種新型進化算法&#xff0c;其核心在于通過自適應基向量和隨機步長的…

上傳本地項目到GitHub

一、在GitHub上創建倉庫 1.點擊右上角頭像–>點擊Your repositories 2.點擊New 3.創建倉庫 網址復制一下&#xff0c;在后面git上傳時會用到 二、打開Git Bash 1.cd 進入項目所在路徑 2.輸入git init 在當前項目的目錄中生成本地的git管理&#xff08;當前目錄下出現.…

14.使用各種讀寫包操作 Excel 文件:輔助模塊

一 各種讀寫包 這些是 pandas 在底層使用的各種讀寫包。無須安裝 pandas&#xff0c;直接使用這些讀寫包就能夠讀寫 Excel 工作簿。可以盡可能地使用 pandas 來解決這類問題&#xff0c;只在 pandas 沒有提供你所需要的功能時才用到讀寫包。 表中沒有 xlwings &#xff0c;因為…

ubuntu ollama+dify實踐

安裝ollama 官網的指令太慢了&#xff0c;使用以下指令加速&#xff1a; export OLLAMA_MIRROR"https://ghproxy.cn/https://github.com/ollama/ollama/releases/latest/download" curl -fsSL https://ollama.com/install.sh | sed "s|https://ollama.com/dow…

spring boot+mybaits多條件模糊查詢和分頁查詢

我們首先寫一下多條件的模糊查詢&#xff0c;首先在controller里面寫一個接口&#xff0c;進行傳參&#xff0c;我們這里要注意&#xff0c;之前寫修改和增加的時候用的注解都是RequestBody,也就是說&#xff01;前端傳過來一個json&#xff0c;數組也行&#xff0c;然后我們后…

HarmonyOS NEXT - 電商App實例四(登錄界面)

登錄界面是用戶進入App的第一步&#xff0c;因此需要簡潔明了&#xff0c;同時保持品牌風格的一致性。如&#xff1a;頂部區域為品牌LOGO展示&#xff0c;增加品牌識別度&#xff1b;中間區域為登錄表單&#xff0c;包含輸入框和按鈕&#xff1b;底部區域為其他登錄方式、注冊入…

探索ima.copilot:個人知識庫搭建的AI新利器

在信息爆炸的時代&#xff0c;知識的積累與管理成為了個人發展的關鍵。面對海量的科研文獻、工作資料和各類信息&#xff0c;如何高效地構建屬于自己的知識體系&#xff0c;是許多人面臨的挑戰。ima.copilot這款AI工具的出現&#xff0c;為解決這一難題提供了新的思路。它憑借強…

圖解多頭注意力機制:維度變化一鏡到底

目錄 一、多頭注意力機制概述二、代碼實現1. pyTorch 實現2. tensorFlow實現 三、維度變化全流程詳解1. 參數設定2. 維度變化流程圖3. 關鍵步驟維度變化 四、關鍵實現細節解析1. 多頭拆分與合并2. 注意力分數計算3. 掩碼處理技巧 五、完整運行示例六、總結與常見問題1. 核心優勢…

Interview preparation.md

Vue 1.1 響應式系統 Vue 3 使用 Proxy 代替 Vue 2 中的 Object.defineProperty 來實現響應式系統。Proxy 可以監聽對象的所有操作&#xff0c;包括屬性的添加和刪除&#xff0c;從而解決了 Vue 2 的一些局限性。 Vue 2&#xff1a;使用 Vue.set 添加響應式屬性 new Vue({el…

2.8滑動窗口專題:最小覆蓋子串

1. 題目鏈接 LeetCode 76. 最小覆蓋子串 2. 題目描述 給定字符串 s 和 t&#xff0c;要求找到 s 中最小的窗口&#xff0c;使得該窗口包含 t 的所有字符&#xff08;包括出現次數&#xff09;。若不存在&#xff0c;返回空字符串。 示例&#xff1a; 輸入&#xff1a;s &quo…

【數據分析大屏】基于Django+Vue汽車銷售數據分析可視化大屏(完整系統源碼+數據庫+開發筆記+詳細部署教程+虛擬機分布式啟動教程)?

目錄 一、項目背景 二、項目創新點 三、項目功能 四、開發技術介紹 五、項目功能展示 六、權威視頻鏈接 一、項目背景 汽車行業數字化轉型加速&#xff0c;銷售數據多維分析需求激增。本項目針對傳統報表系統交互性弱、實時性差等痛點&#xff0c;基于DjangoVue架構構建…

cyberstrikelab lab2

lab2 重生之我是滲透測試工程師&#xff0c;被公司派遣去測試某網絡的安全性。你的目標是成功獲取所有服務器的權限&#xff0c;以評估網絡安全狀況。 先掃一下 ? ? 192.168.10.10 ? ? 騎士cms 先找后臺路徑 http://192.168.10.10:808/index.php?madmin&cind…