串口編程(SerialPort類)


近期由於項目中用到串口編程,而以前有從未使用過,查閱相關資料,先將串口編程整個過程整理如下,以備不時之需。

SerialPort類簡述

此類位於System.IO.Ports命名空間下。用於控制串行端口文件資源,此類提供同步I/O和事件驅動的I/O、對管腳和中斷狀態的訪問以及對串行驅動程序的訪問。

SerialPort類支持一下編碼:ASCIIEncoding、UTF8Encoding、UnicodeEncoding、UTF32Encoding以及mscorlib.dll中定義的代碼頁小於50000或者為54936的所有編碼。(摘自MSDN,具體網址

SerialPort常用屬性

  • BaudRate  獲取或設置串行波特率
  • BreakState 獲取或設置中斷信號狀態
  • BytesToRead 獲取接收緩沖區中數據的字節數
  • BytesToWrite 獲取發送緩沖區中數據的自己數
  • DataBits 獲取或設置每個字節的標准數據位長度(默認為8)
  • DtrEnable 獲取或設置一個值,該值指示Null字節在端口和接收緩沖區之間傳輸時是否被忽略
  • Encoding 獲取或設置傳輸前后的文本轉換的字節編碼
  • IsOpen 獲取一個值,該值指示SerialPort對象的打開或關閉狀態
  • NewLine 獲取或設置用於解釋ReadLine和WriteLine方法調用結束的值
  • Parity 獲取或設置奇偶校驗檢查協議
  • PortName 獲取或設置通信端口,包括但不限於所有可用的COM端口
  • ReadBufferSize 獲取或設置SerialPort輸入緩沖區的大小
  • ReadTimeOut 獲取或設置讀取操作未完成時發生超時之前的毫秒數
  • ReceivedBytesThreshold 獲取或設置DataReceived事件發生前內部輸入緩沖區中的字節數
  • RtsEnable 獲取或設置一個值,該值指示在串行通信中是否啟用請求發送RTS信號
  • StopBits 獲取或設置每個字節的標准停止位數
  • WriteBufferSize 獲取或設置串行端口輸出緩沖區的大小
  • WriteTimeout 獲取或設置寫入操作未完成時發生超時之前的毫秒數

SerialPort的主要方法

  • Close 關閉端口連接,將IsOpen屬性設置成為false,並釋放內部Stream對象
  • Dispose 釋放SerialPort對象使用的非托管資源
  • GetPortNames 獲取當前計算機的串行端口名稱數組
  • Open 打開一個新的串行端口連接
  • Read 從SerialPort輸入緩沖區中讀取
  • ReadByte 從SerialPort輸入緩沖區中同步讀取一個字節
  • ReadChar 從SerialPort輸入緩沖區中同步讀取一個字符
  • ReadExisting 在編碼的基礎上,讀取SerialPort對象的流和輸入緩沖區中所有立即可用的字節
  • ReadLine 一直讀取到輸入緩沖區中的NewLine值
  • ReadTo 一直讀取到輸入緩沖區中指定value的字符串
  • Write 將數據寫入到串行端口輸出緩沖區
  • WriteLine 將指定的字符串和NewLine值寫入到輸出緩沖區
  • DataReceived 表示將處理SerialPort對象的數據接收事件的方法
  • ErrorReceived 表示處理Serialport對象的錯誤事件的方法

SerialPort類編程實例講解

 

01.using System;  
02.using System.Collections.Generic;  
03.using System.ComponentModel;  
04.using System.Data;  
05.using System.Drawing;  
06.using System.Linq;  
07.using System.Text;  
08.using System.Windows.Forms;  
09.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.        private long received_count = 0;//接收計數  
18.        private long send_count = 0;//發送計數  
19.        public SerialportSampleForm()  
20.        {  
21.            InitializeComponent();  
22.        }  
23.        //窗體初始化  
24.        private void 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 = new byte[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.        private void 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.        private void checkBoxNewlineGet_CheckedChanged(object sender, EventArgs e)  
99.        {  
100.            txGet.WordWrap = checkBoxNewlineGet.Checked;  
101.        }  
102.        private void 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,System.Globalization.NumberStyles.HexNumber));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.        private void 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.}  

代碼段來自wuyazhe C# 串口操作系列(1) -- 入門篇,一個標准的,簡陋的串口例子一文,該文非常經典,適合入門,推薦閱讀。

總結

一、進行串口通訊時,需要設置一些相關參數,可以通過設置SerialPort 類的屬性來進行。串口屬性主要包括

.PortName 串口名稱,COM1, COM2等。
.BaudRate 波特率,也就是串口通訊的速度,進行串口通訊的雙方其波特率需要相同,如果用PC連接其他非PC系統,一般地,波特率由非PC系統決定
.Parity 奇偶校驗。可以選取枚舉Parity中的值
.DataBits 數據位
.StopBits 停止位,可以選取枚舉StopBits中的值
.Handshake 握手方式,也就是數據流控制方式,可以選取枚舉Handshake中的值

二、打開與關閉串口

在創建一個SerialPort 對象,設置串口屬性后,可以通過 Open()方法打開串口。數據讀寫完成后,可以通過Close()方法關閉串口。
根據經驗,對於有些系統,在打開串口后,還需要將RtsEnable設置為True,這樣才能讀寫數據,否則不能正常讀寫數據。

三、DataReceived

SerialPort 提供了DataReceived事件。當有數據進入時,該事件被觸發。該事件的觸發由操作系統決定,當有數據到達時,該事件在輔助線程中被觸發。輔助線程的優先級比較低因此並不能確保每個字節的數據到達時,該事件都被觸發

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM