這段時間做了一個和硬件設備通信的小項目,涉及到掃描頭、輸送線、稱重機、貼標機等硬件。和各設備之間通信使用的是串口或網絡(Socket)的方式。掃描頭和貼標機使用的網絡通信,輸送線和稱重機使用的是串口通信。
串口通信,以前一直覺得神秘,沒想到用起來卻這么簡單。當然,這樣簡單要歸功於 .NET 對其操作的封裝。
.NET 里提供了專門操作串口的類 System.IO.Ports.SerialPort,可以操作串口收發數據。只需要 new 一個對象,簡單配置一下相關屬性,就可以使用串口收發數據了。
SerialPort 類常用的屬性有 PortName、BaudRate、DataBits、StopBits、Parity 等。PortName 是端口名稱,如COM1、COM2等,默認COM1;BaudRate 是波特率,默認 9600;DataBits 是數據位,默認是 8;StopBits 是停止位,默認是System.IO.Ports.StopBits.One、Parity 設定奇偶校驗,默認是System.IO.Ports.Parity.None。
其中端口名稱設置的是你通信使用的本地端口的名稱,其它參數,一般默認。具體意思?關我毛事!和設備約定相同就行了。
所以,一般來說,使用串口的准備操作,就這么簡單:
1 System.IO.Ports.SerialPort com1 = new System.IO.Ports.SerialPort(); 2 com1.PortName = "COM1"; //端口名稱,默認COM1 3 com1.BaudRate = 9600; //波特率,默認9600 4 com1.DataBits = 8; //數據位,默認8 5 com1.StopBits = System.IO.Ports.StopBits.One; //停止位,默認 System.IO.Ports.StopBits.One 6 com1.Parity = System.IO.Ports.Parity.None; //奇偶校驗,默認 System.IO.Ports.Parity.None
如果都使用的默認參數,還可以精簡成這樣:
1 System.IO.Ports.SerialPort com1 = new System.IO.Ports.SerialPort("COM1");
當然,對硬件設備的操作需要在使用前后打開或關閉資源。SerialPort 類提供了 Open 和 Close 方法用來打開或半閉串口。
打開以后,就可以向端口讀寫數據了。
SerialPort 類提供了 Write 和 WriteLine 兩個方法向串口發送數據。Write 發送一個 byte 數組,和一般的流操作類似;WriteLine 可以直接發送一個字符串。
SerialPort 類提供了 Read、ReadByte、ReadChar、ReadExisting、ReadLine 和 ReadTo 等方法可以從串口中讀取數據。Read 可以把數據讀取到一個 byte 數組;ReadByte 可以讀取一個字節;ReadChar 可以讀取一個字符;ReadExisting 可以讀取當前可讀取的所有數據;ReadLine 可以讀取一行數據;ReadTo 這個我沒用過。
當然如果沒有數據,就讀取不到了。我們可以使用 BytesToRead 屬性獲取可讀取的數據長度,如果長度為 0,就說明串口中沒有接收到數據。如果需要監聽端口數據,就可以單獨開一個線程反復讀取。
除了使用反復讀取來監聽串口數據,還可以使用 SerialPort 類提供的 DataReceived 事件來監聽串口中接收到的數據,當串口中有可讀取的數據,系統會自動觸發 DataReceived 事件處理程序。設置代碼如下:
1 System.IO.Ports.SerialPort com1 = new System.IO.Ports.SerialPort("COM1"); 2 com1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(Com1_DataReceived);
回調方法聲明如下:
1 private void Com1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) 2 { 3 4 }
理論講完了,下面寫一個簡單的 Demo 實驗一下。
因為要驗證收發數據,需要用到一個串口虛擬化的軟件。該軟件可以在 PC 上成對的虛擬串口,可以實現對 COM1 發的數據,COM2 中接收到。
環境搭建好以后,編寫代碼試着在單擊按鈕的時候,將文本框的內容寫入 COM1,然后從 COM2 中讀取,並使用對話框彈出來。
新建一個窗體,拖入一個文本框 textbox1 和一個按鈕 button1,然后添加操作代碼,如下:
1 public partial class Form1 : Form 2 { 3 System.IO.Ports.SerialPort COM2 = null; 4 5 public Form1() 6 { 7 InitializeComponent(); 8 } 9 10 private void Form1_Load(object sender, EventArgs e) 11 { 12 COM2 = new System.IO.Ports.SerialPort("COM2"); 13 COM2.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(Com2_DataReceived); 14 COM2.Open(); 15 } 16 17 private void Form1_FormClosing(object sender, FormClosingEventArgs e) 18 { 19 COM2.Close(); 20 COM2 = null; 21 } 22 23 private void button1_Click(object sender, EventArgs e) 24 { 25 System.IO.Ports.SerialPort com1 = new System.IO.Ports.SerialPort("COM1"); 26 com1.Open(); 27 com1.WriteLine(this.textBox1.Text); 28 com1.Close(); 29 } 30 31 private void Com2_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) 32 { 33 System.IO.Ports.SerialPort com = (System.IO.Ports.SerialPort)sender; 34 MessageBox.Show(com.ReadExisting()); 35 } 36 }
運行,測試,如圖: