1. 程式人生 > >C# 串列埠操作系列(1) -- 入門篇,一個標準的,簡陋的串列埠例子。

C# 串列埠操作系列(1) -- 入門篇,一個標準的,簡陋的串列埠例子。

我假設讀者已經瞭解了c#的語法,本文是針對剛打算解除串列埠程式設計的朋友閱讀的,作為串列埠程式設計的入門範例,也是我這個系列的基礎。

我們的開發環境假定為vs2005(雖然我在用vs2010,但避免有些網友用2005,不支援lambda,避免不相容,就用2005來做例子)

一個基本的串列埠程式,既然是個程式了。我們就先從功能說起,包含

串列埠選擇

波特率選擇

開啟

關閉

接受資料顯示

傳送資料輸入

傳送資料

資料量提示以及歸零

好吧,有了這些功能,我們就先畫出介面。例如:

這裡,波特率就定死幾種好了。直接介面上新增2400,4800,9600,19200,38400,57600,115200

comboPortName這裡,為了我們的軟體能通用所有電腦避免每次查詢的效率損失,我們使用微軟提供的列舉方式,程式碼如下:

  1. string[] ports = SerialPort.GetPortNames();  
  2. Array.Sort(ports);  
  3. comboPortName.Items.AddRange(ports);  

顯然,我們需要定義一個SerialPort物件。新增DataReceived事件響應收到資料,還有一個重點,我們需要記得設定NewLine屬性哦。好想有的版本不設定的時候,WriteLine和Write效果一樣。

所以,我們需要初始化SerialPort物件,例如:

  1. //初始化SerialPort物件
  2. comm.NewLine = "/r/n";  
  3. comm.RtsEnable = true
    ;//根據實際情況吧。
  4. //新增事件註冊
  5. comm.DataReceived += comm_DataReceived;  

 初始化好串列埠,簡單的編寫開啟,關閉方法,編寫介面響應的是否自動換行,如何復位計數器,傳送方法。以及資料處理。因為我已經寫了完整注視,我就直接貼程式碼了。

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel;  
  4. using System.Data;  
  5. using System.Drawing;  
  6. using System.Linq;  
  7. using System.Text;  
  8. using System.Windows.Forms;  
  9. using System.IO.Ports;  
  10. using System.Text.RegularExpressions;  
  11. namespace SerialportSample  
  12. {  
  13.     public partial class SerialportSampleForm : Form  
  14.     {  
  15.         private SerialPort comm = new SerialPort();  
  16.         private StringBuilder builder = new StringBuilder();//避免在事件處理方法中反覆的建立,定義到外面。
  17.         privatelong received_count = 0;//接收計數
  18.         privatelong send_count = 0;//傳送計數
  19.         public SerialportSampleForm()  
  20.         {  
  21.             InitializeComponent();  
  22.         }  
  23.         //窗體初始化
  24.         privatevoid Form1_Load(object sender, EventArgs e)  
  25.         {  
  26.             //初始化下拉串列埠名稱列表框
  27.             string[] ports = SerialPort.GetPortNames();  
  28.             Array.Sort(ports);  
  29.             comboPortName.Items.AddRange(ports);  
  30.             comboPortName.SelectedIndex = comboPortName.Items.Count > 0 ? 0 : -1;  
  31.             comboBaudrate.SelectedIndex = comboBaudrate.Items.IndexOf("9600");  
  32.             //初始化SerialPort物件
  33.             comm.NewLine = "/r/n";  
  34.             comm.RtsEnable = true;//根據實際情況吧。
  35.             //新增事件註冊
  36.             comm.DataReceived += comm_DataReceived;  
  37.         }  
  38.         void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)  
  39.         {  
  40.             int n = comm.BytesToRead;//先記錄下來,避免某種原因,人為的原因,操作幾次之間時間長,快取不一致
  41.             byte[] buf = newbyte[n];//宣告一個臨時陣列儲存當前來的串列埠資料
  42.             received_count += n;//增加接收計數
  43.             comm.Read(buf, 0, n);//讀取緩衝資料
  44.             builder.Clear();//清除字串構造器的內容
  45.             //因為要訪問ui資源,所以需要使用invoke方式同步ui。
  46.             this.Invoke((EventHandler)(delegate
  47.             {  
  48.                 //判斷是否是顯示為16禁止
  49.                 if (checkBoxHexView.Checked)  
  50.                 {  
  51.                     //依次的拼接出16進位制字串
  52.                     foreach (byte b in buf)  
  53.                     {  
  54.                         builder.Append(b.ToString("X2") + " ");  
  55.                     }  
  56.                 }  
  57.                 else
  58.                 {  
  59.                     //直接按ASCII規則轉換成字串
  60.                     builder.Append(Encoding.ASCII.GetString(buf));  
  61.                 }  
  62.                 //追加的形式新增到文字框末端,並滾動到最後。
  63.                 this.txGet.AppendText(builder.ToString());  
  64.                 //修改接收計數
  65.                 labelGetCount.Text = "Get:" + received_count.ToString();  
  66.             }));  
  67.         }  
  68.         privatevoid buttonOpenClose_Click(object sender, EventArgs e)  
  69.         {  
  70.             //根據當前串列埠物件,來判斷操作
  71.             if (comm.IsOpen)  
  72.             {  
  73.                 //開啟時點選,則關閉串列埠
  74.                 comm.Close();  
  75.             }  
  76.             else
  77.             {  
  78.                 //關閉時點選,則設定好埠,波特率後開啟
  79.                 comm.PortName = comboPortName.Text;  
  80.                 comm.BaudRate = int.Parse(comboBaudrate.Text);  
  81.                 try
  82.                 {  
  83.                     comm.Open();  
  84.                 }  
  85.                 catch(Exception ex)  
  86.                 {  
  87.                     //捕獲到異常資訊,建立一個新的comm物件,之前的不能用了。
  88.                     comm = new SerialPort();  
  89.                     //現實異常資訊給客戶。
  90.                     MessageBox.Show(ex.Message);  
  91.                 }  
  92.             }  
  93.             //設定按鈕的狀態
  94.             buttonOpenClose.Text = comm.IsOpen ? "Close" : "Open";  
  95.             buttonSend.Enabled = comm.IsOpen;  
  96.         }  
  97.         //動態的修改獲取文字框是否支援自動換行。
  98.         privatevoid checkBoxNewlineGet_CheckedChanged(object sender, EventArgs e)  
  99.         {  
  100.             txGet.WordWrap = checkBoxNewlineGet.Checked;  
  101.         }  
  102.         privatevoid buttonSend_Click(object sender, EventArgs e)  
  103.         {  
  104.             //定義一個變數,記錄傳送了幾個位元組
  105.             int n = 0;  
  106.             //16進位制傳送
  107.             if (checkBoxHexSend.Checked)  
  108.             {  
  109.                 //我們不管規則了。如果寫錯了一些,我們允許的,只用正則得到有效的十六進位制數
  110.                 MatchCollection mc = Regex.Matches(txSend.Text, @"(?i)[/da-f]{2}");  
  111.                 List<byte> buf = new List<byte>();//填充到這個臨時列表中
  112.                 //依次新增到列表中
  113.                 foreach (Match m in mc)  
  114.                 {  
  115.                     buf.Add(byte.Parse(m.Value));  
  116.                 }  
  117.                 //轉換列表為陣列後傳送
  118.                 comm.Write(buf.ToArray(), 0, buf.Count);  
  119.                 //記錄傳送的位元組數
  120.                 n = buf.Count;  
  121.             }  
  122.             else//ascii編碼直接傳送
  123.             {  
  124.                 //包含換行符
  125.                 if (checkBoxNewlineSend.Checked)  
  126.                 {  
  127.                     comm.WriteLine(txSend.Text);  
  128.                     n = txSend.Text.Length + 2;  
  129.                 }  
  130.                 else//不包含換行符
  131.                 {  
  132.                     comm.Write(txSend.Text);  
  133.                     n = txSend.Text.Length;  
  134.                 }  
  135.             }  
  136.             send_count += n;//累加發送位元組數
  137.             labelSendCount.Text = "Send:" + send_count.ToString();//更新介面
  138.         }  
  139.         privatevoid buttonReset_Click(object sender, EventArgs e)  
  140.         {  
  141.             //復位接受和傳送的位元組數計數器並更新介面。
  142.             send_count = received_count = 0;  
  143.             labelGetCount.Text = "Get:0";  
  144.             labelSendCount.Text = "Send:0";  
  145.         }  
  146.     }  
  147. }  

至此,一個標準的串列埠除錯助手就完成了。留下一個思考題,如果接收資料後,更新介面的時候,尚未操作完成,此時併發了關閉串列埠的操作。程式會如何呢?敬請閱讀《C# 串列埠操作系列(2) -- 如何避免關閉串列埠偶爾軟體死鎖》。

//append by wuyazhe @2011-5-26

上面有一點疏漏,源自第一篇,結果到這裡還是沒修改,原始碼中有一行,需要修改一下。

//傳送按鈕中

buf.Add(byte.Parse(m.Value));

要修改為

buf.Add(byte.Parse(m.Value,System.Globalization.NumberStyles.HexNumber));

相關推薦

C# 串列操作系列(1) -- 入門一個標準簡陋串列例子

我假設讀者已經瞭解了c#的語法,本文是針對剛打算解除串列埠程式設計的朋友閱讀的,作為串列埠程式設計的入門範例,也是我這個系列的基礎。 我們的開發環境假定為vs2005(雖然我在用vs2010,但避免有些網友用2005,不支援lambda,避免不相容,就用2005來做例子)

C# 串列操作系列(1) -- 入門一個標準簡陋串列例子

我假設讀者已經瞭解了c#的語法,本文是針對剛打算解除串列埠程式設計的朋友閱讀的,作為串列埠程式設計的入門範例,也是我這個系列的基礎。 我們的開發環境假定為vs2005(雖然我在用vs2010,但避免有些網友用2005,不支援lambda,避免不相容,就用2005來做例子

react-native系列(1)入門:瞭解RN前景和入門指引

React-Native是一門用於開發移動應用程式的開源技術。 隨著原生開發Android和IOS移動應用的成本越來越高,很多企業選擇使用跨平臺一站式開發的React-Native(簡稱RN)作為替代方案。在Facebook的引領下,國外很多大廠也紛紛使用RN來開發移動應用程式,構建出世界一

ML.NET技術研究系列1-入門

近期團隊在研究機器學習,希望通過機器學習實現補丁釋出評估,系統異常檢測。業務場景歸納一下: 收集整理資料(釋出相關的異常日誌、告警資料),標識出補丁釋出情況(成功、失敗) 選擇一個機器學習的Model進行Train訓練 基於訓練出的模型(準確度要高)進行最新補丁釋出情況預測 典型的機器學習-監

C# 串列操作系列(5)--通訊庫雛形

串列埠是很簡單的,編寫基於串列埠的程式也很容易。新手們除了要面對一堆的生僻概念,以及跨執行緒訪問的細節,還有一個需要跨越的難題,就是協議解析,上一篇已經說明了: 一個二進位制格式的協議一般包含: 協議頭 + 資料段長度 + 資料  + 校驗 一個Ascii格式的文字協議,一般

C# 基礎知識系列- 17 實戰 編寫一個小工具(1

# 0. 前言 這是對C# 基礎系列的一個總結,現在我們利用之前學到的知識做一個小小的工具來給我們使用。 如果有看過IO篇的小夥伴,應該有印象。當時我提過一個場景描述,我們在平時使用系統的時候,經常會為了找某個檔案的位置而煩惱。那麼我們現在嘗試寫一個控制檯程式來幫助我們找檔案的具體位置。 # 1. 分析

C# 資料操作系列 - 1. SQL基礎操作

# 0.前言 前篇介紹了一些資料庫的基本概念和以及一些常見的資料庫,讓我們對資料庫有了一個初步的認識。這一篇我們將繼續為C#資料操作的基礎填上一個空白-SQL語句。 SQL(Structured Query Language,結構化查詢語言)是一種特定的程式語言,用於管理資料庫系統,操作資料甚至編寫一些程

Redis學習筆記1--入門

ase list ica cati ctu apple string replace first 一、Redis簡介: Redis(http://redis.io)是一款開源的、高性能的鍵-值存儲(key-value store),它是用ANSI C來編寫。Redis的項目

c++調用python系列(1): 結構體作為入參及返回結構體

pac 格式 lob 打包成 def 程序 png 校驗 upload 最近在打算用python作測試用例以便對遊戲服務器進行功能測試以及壓力測試; 因為服務器是用c++寫的,采用的TCP協議,當前的架構是打算用python構造結構體,傳送給c++層進行socket

Python系列入門——HDFS

system rec urn cep gpo user raise ret append Python系列之入門篇——HDFS 簡介 HDFS (Hadoop Distributed File System) Hadoop分布式文件系統,具有高容錯性,適合部署在廉價的機器上

Mybatis學習系列(1) –– 入門簡介

connector ring cti 行操作 底層 數據庫連接 lean lose style MyBatis簡介 Mybatis是Apache的一個Java開開源項目,是一個支持動態Sql語句的持久層框架。Mybatis可以將Sql語句配置在XML文件中,避免將Sql語

C++入門——輸入一個整數並將這個整數分別以八進位制十進位制十六進位制輸出;同時輸入一個布林值並且以布林值的方式打印出來

C++入門篇 輸入一個整數並將這個整數分別以 八進位制,十進位制,十六進位制輸出; 同時輸入一個布林值並且以 布林值的方式打印出來 注意:執行的時候需要按 ctrl鍵+F5 如果想只按F5就執行,在return 0;前面加一段程式碼: system("pause"); 同時需要

Elasticsearch頂尖高手系列-快速入門

01.課程介紹02.用大白話告訴你什麼是Elasticsearch03.Elasticsearch的功能、適用場景以及特點介紹04.手工畫圖剖析Elasticsearch核心概念:NRT、索引、分片、副本等05.在windows上安裝和啟動Elasticseach06.快速入門案例實戰之電商網站商品管理:叢集

超詳細的redis學習(1)-入門

什麼是Redis 基本概念 redis是一個開源的、使用C語言編寫的、支援網路互動的、可基於記憶體也可持久化的Key-Value資料庫(非關係性資料庫)。 redis的優勢 速度快,因為資料存在

TensorRT 系列入門-優化特點

一 tensorTR對於kernel launch以及每層tensor data讀取的速度不對稱的問題的解決: (1)(縱向融合)通過融合相同順序的操作來減少Kernel launch的消耗以及避免層之間的讀寫操作.如卷積;bias和Relu層可以融合成一個kernel,這裡

Docker系列入門-安裝docker

Docker 提供了兩個版本:社群版 (CE) 和企業版 (EE)。 Docker 社群版 (CE) 是開發人員和小型團隊開始使用 Docker 並嘗試使用基於容器的應用的理想之選,所以這裡我們來說一下Docker社群版的安裝 作業系統要求 64位 CentOS 這裡只說明cento

react-native系列(4)入門:在VSCode中配置ESLint(程式碼檢測工具)

ESLint是一套javascript程式碼檢測工具。要記住,程式碼也是寫給人看的,所以一定要注意程式碼的編寫規範。ESLint可以根據自己設定的規則實現對程式碼的檢測,從而規範了程式碼的風格。本篇內容主要介紹如何在VSCode中使用ESLint。 ESLint的官網地址是:https://

react-native系列(3)入門:使用VSCode及除錯程式碼(debug)

VSCode是一款程式碼編輯器,是微軟的產品,這款編輯器非常受歡迎的一個原因是它支援很多外掛,當然也包括RN開發的外掛。VSCode的下載頁是:https://code.visualstudio.com/,直接下載安裝即可。 安裝好後,可以通過 ' Open Folder ' 選項

react-native系列(2)入門:Windows系統下配置Android開發環境

本文主要內容是在Window系統下配置Android APP的開發環境,配置過程將會有點麻煩,請大家需要有點耐心。當然大家也可以參考RN官網的配置過程,但實際上很多開發者根據官網步驟並沒能配置出完整的RN開發環境。目前RN的最新版本是0.57,我們將以這個版本為例配置Android的開發環境。

C++向量圖形庫系列(1)——向量圖形庫亂談

 本系列篇章的主要內容是講解向量圖形庫的編譯、開發和使用。並不對他們周邊的內容做過多的描述,如效能對比等。本人部落格所有文章全部都是個人原創,並保留一切權利。不是原創的內容本人一定會註明“轉載”字樣。所以如果您需要轉載,請註明來源,謝謝。     向量圖形,這是一個非