2011年12月20日 星期二

C# Serial Port Communication #3

看完上一篇學會用 SerialPort.Write() 寫資料到 serial port 的方法後,接著我們來學習用 SerialPort.Read() method 讀取 serial port 的資料。SerialPort 有很多種 Read methods,例如 Read(), ReadByte(), ReadChar(), ReadExisting(), ReadLine(), ReadTo() 等,使用者可以根據需要挑選適合的來使用。

底下將以幾個例子示範如何讀取 SerialPort。

Arduino Sketch

我們在「Lab8 使用光敏電阻控制 LED 的開關」看過 Serial Port 的程式範例 (Photocell.pde),如下,這支程式非常的簡單,它的功能是讀取光敏電阻並將讀值輸出到 Serial Port:

我們可以用 Arduino IDE 內建的 Serial Monitor 來跟 Arduino 通訊。在把上列程式編譯並上傳到 Arduino 板子上後,打開 Serial Monitor,然後你就會看到 Serial Port 不斷地收到從 Arduino 傳送過來的光敏電阻讀值:

image_thumb17
▲ Serial Monitor 所用的 baud rate 必須與程式 Serial.begin(xxxx) 相同

請將這支 Arduino 程式上傳到 Arduino 板子上。接著我們來看如何用 C# 讀取 Arduino 丟出來的資料。

範例一:SimpleReadDemo

第一個範例是 SimpleReadDemo,這個範例示範了用 C# 讀取 SerialPort 最簡單的方法:

程式碼很簡單,在設定好 serial port 的參數後 (COM5, 9600, n,8,1),程式接著會打開 serial port 然後執行一個無窮迴圈,迴圈裏只是用 SerialPort.ReadLine() 從 serial port 上讀取一行資料再印到 Console 上。

執行畫面如下:

image

範例二: ReadDemo-Console

第二個範例 ReadDemo-Console 示範事件驅動 I/O 的寫法:

這支程式最大的不同是底下這幾行程式:

這幾行程式註冊了一個 DataReceivedHandler 函式,之後當 serial port 有資料時會產生 DataReceived 事件,程式就會自動呼叫 DataReceivedHandler 函式,然後 DataReceivedHandler 函式才會去讀取 serial port 的資料。

這種寫法的優點是你的應用程式可以做其它事情,例如更新 user interface 或是做其它計算等。

這個範例執行結果跟前一個範例相同。

範例三:ReadDemo

第三個範例 ReadDemo 是前一個範例的 GUI 版本,一樣是示範事件驅動 I/O 的寫法:

在 btnOpen_Click 中程式一樣註冊了一個 DataReceivedHandler 函式:

之後當 serial port 有資料時會產生 DataReceived 事件,程式就會自動呼叫 DataReceivedHandler 函式,不過這次 DataReceivedHandler 函式寫法稍有不同:

DataReceivedHandler 函式現在會透過 delegate 及 Invoke 來引發 AddData() 函式:

會這麼是因為 Windows Forms 是 Multi-threading 的機制,如果不這麼寫,而直接在 DataReceivedHandler 把資料丟到 TextBox,就會遇到「跨執行緒作業無效」這類錯誤。

程式執行畫面如下:

image
▲ 尚未開啟 serial port 前的畫面

image
▲ 開啟 serial port 後,Arduino 傳過來的資料會顯示在 TextBox 上

範例程式下載

這篇文章的範例程式可以在底下的網址取得:

http://goo.gl/TH9SS

參考資料

0 意見: