//Logo Image
作者:林怡錦(2012-05-04);推薦:徐業良(2012-05-05)
附註:本文為元智大學機械系自動化機械設計課程Arduino使用教材。

Visual Studio C# 2010使用COM port通訊

本文將說明如何於Visual Studio C# 2010(VC#)Windows Form應用程式專案中使用COM port通訊並以Arduino Uno進行實作。

1.    基本輸入/輸出範例

COM port又稱為Serial Port(序列埠),為在裝置及微處理器之間傳送資料所使用的通道,依其序列傳輸協議的不同可以區分為RS-232RS-422RS-485Univeral Serial Bus(USB)以及RJ-45COM port可以用於連接印表機、舊式序列埠滑鼠以及行動裝置等裝置至電腦。本節將使用具有簡單輸入/輸出的Arduino程式,說明如何編寫VC#以進行如在Arduino Serial Monitor上所見的簡單輸入,並以手動觸發讀取事件。

1.1 Arduino Uno程式

以下為一具有簡單輸入輸出Arduino程式之程式碼,其鮑率設定為9600,而當使用者輸入字元並傳送時,Arduino將會回傳「key in chart is : 你所輸入的字元」,並以間隔時間一秒回傳數字1~5如圖1

char str_in;

 

void setup(){

  Serial.begin(9600);

}

 

void loop(){

  if (Serial.available() > 0){

    str_in = Serial.read();

    Serial.print("key in chart is : ");

    Serial.println(str_in);

delay(1000);

Serial.println ('1', BYTE); delay(1000);

Serial.println ('2', BYTE); delay(1000);

Serial.println ('3', BYTE); delay(1000);

Serial.println ('4', BYTE); delay(1000);

Serial.println ('5', BYTE); delay(1000);

  }

}

1. Arduino Serial Monitor視窗

1.2 VC#程式實作

本節將說明如何編寫VC#程式,以進行簡單輸入與按鍵觸發讀取事件。程式開始運行後,首先設定程式中會使用到的COM port名稱再開啟該連線,於命令區輸入指令,按下傳送鍵將指令經由COM port連線傳給Arduino,再按接收鍵觸發讀取事件,程式結束時將關閉該COM port,程式流程如圖2

2. 程式流程圖

(1)  VC#新建專案與介面設置

先於VC#中建立新的Windows Form應用程式專案,如圖3。以滑鼠快速點擊兩下或拖曳工具箱中的SerialPort元件圖示,如圖4,至Form1圖形視窗畫面中,即可在Form1中新增SerialPort元件。以滑鼠單擊Form1圖形視窗中的SerialPort元件,即可於屬性欄中檢視與編輯其基本屬性,若畫面中並無屬性欄可點選上排工具列圖示以加入屬性欄,如圖5。基本常用SerialPort屬性有NameBaudRate以及PortNameNameSerialPort於程式內部的變數名稱;BaudRate即鮑率,用以表示COM port傳輸速率其單位為單位時間內傳輸的信號數,傳送與接收裝置需使用相同鮑率,才能正確地接收訊號,本文中之Arduino程式已設定鮑率為9600,故此欄位也應填入9600PortName為用來通訊的COM port名稱。

3. 新增Windows Form應用程式專案畫面

4. 工具箱中的SerialPort元件

5. 屬性視窗圖示位置

由於每次使用的COM port名稱並不完全相同,所以加入TextBox元件以填入該次使用的COM port名稱,再加入一個TextBox元件以填入欲傳送給Arduino的指令,加入4Button元件以觸發開啟COM port、傳送指令、讀取訊息以及關閉COM port事件。元件類型、本文程式碼中的名稱以及用途於表1,參考程式介面如圖6

1. 視窗介面元件說明

元件類型

程式碼中名稱

用途

TextBox

txbCOM

填入該次使用的COM port名稱

Button

btnOpen

點選以開啟COM port連線

TextBox

txbWrite

填入欲傳送的指令

Button

btnWrite

點選以傳送txbWrite內的指令給Arduino

Button

btnRead

點選以讀取Arduino的輸出

Button

btnClose

點選以關閉COM port連線

6. 參考程式介面

(2)  VC#程式編寫

接下來開始編寫程式碼的部分,首先加入System.IO.Ports命名空間,才能使用COM port的相關功能,程式碼如下:

using System.IO.Ports;

快速連續點擊兩下編輯視窗介面中的btnOpen元件,VC#將會自動產生按鍵觸發事件。當btnOpen_Click事件被觸發,SerialPort1PortName將被txbCOM中的文字取代,再開啟該COM port連線供應用程式使用,程式碼如下:

private void btnOpen_Click(object sender, EventArgs e)

        {

            serialPort1.PortName = txbCOM.Text;

            serialPort1.Open();

        }

快速連續點擊兩下編輯視窗介面中的btnWrite元件,以產生按鍵觸發事件。當btnWrite_Click事件被觸發,將會藉由COM port傳送txbWrite元件中的文字指令,相當於點擊Arduino Serial Monitor中的Send按鍵,程式碼如下:

private void btnWrite_Click(object sender, EventArgs e)

        {

            serialPort1.Write(txbWrite.Text);

        }

快速連續點擊兩下編輯視窗介面中的btnRead元件,以產生按鍵觸發事件。當btnRead_Click事件被觸發,將會讀取輸入緩衝區中,在換行符號(\n)前之內容,並於輸出視窗中顯示,程式碼如下:

private void btnRead_Click(object sender, EventArgs e)

        {

            Console.Write(serialPort1.ReadLine());

        }

快速連續點擊兩下編輯視窗介面中的btnClose元件,以產生按鍵觸發事件。當btnClose_Click事件被觸發,將會關閉使用中的COM port連線,程式碼如下:

private void btnClose_Click(object sender, EventArgs e)

        {

            serialPort1.Close();

        }

1.3 透過VC#Arduino通訊

完成上述ArduinoVC#程式後,先於裝置管理員中查看Arduino所用的COM port名稱,如圖7。可以看到圖中Arduino使用的COM port名稱為COM7

7. 裝置管理員查看COM port名稱

執行VC#程式,於txtCOM元件中填入COM7,點選btnOpen以開啟該COM port連線供應用程式使用。再於txtWrite中填入指令後,點選btnWrite,傳送指令給Arduino。點選數次btnRead,可在輸出區看到VC#依序輸出所接收到的一行一行輸入,最後結果會和在Aruino Serial Monitor上所看到的一樣,如圖8

8. 程式運行的結果

2.    進階範例

上述範例程式在讀取COM port回傳資料的時候,需手動觸發讀取事件,但有時會希望程式可以在一有輸入時便自動讀取與顯示。而且每次所使用的COM port名稱皆不完全相同,所以如果可以在程式開始執行時便自動搜尋COM port名稱,以選擇取代手動輸入的方式將會更方便使用。接下來說明如何改寫VC#以達成這兩項功能。

2.1 VC#程式改寫

(1)  自動讀取與顯示功能

若想要可以自動讀取與顯示,需要在Form1中新增DataReceived事件,當有新的訊息傳入時,執行serialPort1_DataReceived函數將收到的訊息讀取與顯示,程式碼如下:

public Form1()

        {

            InitializeComponent();

 

   serialPort1.DataReceived += new           SerialDataReceivedEventHandler(serialPort1_DataReceived);

        }

 

        void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)

        {

            String data = serialPort1.ReadLine();

            Console.Write("datareceived: " + data);

        }

(2)  自動搜尋所有COM port名稱

若要可以在開啟時搜尋電腦所有COM port名稱,可將txtCOMTextBox元件改成可顯示選項的ComboBox元件並命名為cbbCOM。再快速連續點擊視窗介面,產生Form1_Load事件。當Form1開啟時,會先搜尋電腦所有COM port名稱,並將其名稱儲存在serialPorts陣列中,再逐一加入cbbCOM元件的項目中,程式碼如下:

private void Form1_Load(object sender, EventArgs e)

        {

            string[] serialPorts = SerialPort.GetPortNames();

           

            foreach (string serialPort in serialPorts) {

                cbbCOM.Items.Add(serialPort);

                if (cbbCOM.Items.Count > 0) {

                    cbbCOM.SelectedIndex = 0;

                }

            }

        }

而在開啟COM port時,由於不再是使用txtCOM元件提供COM port名稱,而是使用cbbCOM中被選中的項目名稱,所以程式碼需改寫成:

private void btnOpen_Click(object sender, EventArgs e)

        {

            serialPort1.PortName = (string)cbbCOM.SelectedItem;

            serialPort1.Open();

        }

完成上述更改後,即可自動搜尋COM port名稱以及自動顯示接收到的訊息。

2.2 透過VC#Arduino通訊

修改後的程式運作如圖9,可以經ComboBox元件選擇COM port名稱,並且自動跳出回傳之訊息,在使用上將方便許多。

9. 修改後程式運作

參考資料:

MSDN: http://msdn.microsoft.com/zh-tw/library/system.io.ports.serialport.aspx