USB通信 (VC#)                          

  



■ PIC18 CDCクラスMicrochip社デモソフト 

  PICとUSB通信を行なう場合、マイクロチップ社から提供(公開)されているいるUSBフレームワークのCDCクラスを使うとPC側のソフトは
 RS232Cの送受信のようにあつかうことができます。このサンプルソフトがマイクロチップ社のHPに公開されています。以下のプログラムは 
 マイクロチップ社のMCHPFSUSB Framework 2.3をダウンロードして解凍後PCにできる …\Microchip Solutions\
 USB Device - CDC - Basic Demo\PC Software ExampleVCsharp 2005フォルダに収納されているC#のサンプルプログラムです。この
 ソフトは マイクロチップ  DemoBoard(PICDEM FS USB DM163025)($59.99ドル)用デモソフトのPC側ソフトです。 コメント行は翻訳、
 、削除、追記等をしていますが 、ソースコードの変更は行なっていません。 全体のハード 及びPIC側のソフトは 全体&PIC側を参照
 願います

       <プログラム>
  
        
        delegate void SetTextCallback(string text);//デリゲート宣言

      
        public Form1()
        {
            InitializeComponent();

            UpdateCOMPortList();    //使用可能COMポートリスト更新
        }


        private void UpdateCOMPortList()    //使用可能COMポートリスト作成
        {
            int i;
            bool foundDifference;

            i = 0;
            foundDifference = false;

            if (lstCOMPorts.Items.Count == SerialPort.GetPortNames().Length)
            {
                foreach (string s in SerialPort.GetPortNames())
                {
                   
                    if (lstCOMPorts.Items[i++].Equals(s) == false)
                    {
                        foundDifference = true;
                    }
                }
            }
            else
            {
                foundDifference = true;
            }

            if (foundDifference == false)
            {
                return;
            }

            lstCOMPorts.Items.Clear();
            foreach (string s in SerialPort.GetPortNames())
            {
                lstCOMPorts.Items.Add(s);
            }
            lstCOMPorts.SelectedIndex = 0;
        }

        private void timer1_Tick(object sender, System.EventArgs e) //COMポートリストの周期的更新
        {
                UpdateCOMPortList();
        }

        private void btnConnect_Click(object sender, System.EventArgs e)    //選択されたCOMポートをオープンする
        {
         
            try
            {
                serialPort1.PortName = lstCOMPorts.Items[lstCOMPorts.SelectedIndex].ToString();

                serialPort1.Open();  //COMポートオープン

                btnConnect.Enabled = false;
                lstCOMPorts.Enabled = false;
                btnClose.Enabled = true;

                txtDataReceived.Clear();
                txtDataReceived.AppendText("Connected.\r\n");
            }
            catch
            {
                //If there was an exception, then close the handle to 
                //  the device and assume that the device was removed
                btnClose_Click(this, null);
            }
        }

        private void btnClose_Click(object sender, System.EventArgs e)  //COMポートのクローズ
        {
            btnClose.Enabled = false;
            btnConnect.Enabled = true;
            lstCOMPorts.Enabled = true;

            try
            {
                serialPort1.DiscardInBuffer();  //入力バッファーのデータ破棄
                serialPort1.DiscardOutBuffer(); //出力バッファーのデータ破棄

                serialPort1.Close();
            }
            //If there was an exeception then there isn't much we can
            //  do.  The port is no longer available.
            catch { }
        }

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) //データ受信
        {
            try
            {
                SetText(serialPort1.ReadExisting());
            }
            catch
            {
                //If there was an exception, then close the handle to 
                //  the device and assume that the device was removed
                btnClose_Click(this, null);
            }
        }

       
        private void SetText(string text)   //受信スレッドからメインスレッドへの書き出し
        {
            if (txtDataReceived.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                Invoke(d, new object[] { text });
            }
            else
            {
                //If this function was called from the same thread that 
                //  holds the required objects then just add the text.
                txtDataReceived.AppendText(text);
            }
        }
        
         private void btnSendData_Click(object sender, System.EventArgs e)  //テキストボックス内のデータをCOMポート経由で送信
        {
            try
            {
                 serialPort1.Write(txtData.Text);
            }
            catch
            {
                //If there was an exception, then close the handle to 
                //  the device and assume that the device was removed
                btnClose_Click(this, null);
            }
        }
          

PIC18F4550−PC 間  CDCクラス通信
 ( 自作PICキバン + Microchip社デモソフト)

<動作結果>
    デモソフト:
        Basic Demo

@コンボボックスからCOM8ポートを選択

AConnectボタンをクリック
  
→リッチテキストボックスにConnectedが表示される

BPICキバン上のSWを押すと文字列
 Button Pressed--がUSB送信され、左記ウィンドウの リッチテキストボックスに表示される。

Cテキストボックスに5をキーインて、Send Dataボタンを クリックする。
  →PICキバン側で+1インクリメントされた6がUSB通信で返信され、これが左記リッチテキストボックスに表示される

      ★全体のハード 及びPIC側のソフト
                 → 全体&PIC側参照

    デモソフト:

        Serial Emulator


送信側(USB通信):PICDEMサンプルソフト
受信側(RS232C通信):Tera Term

     

@左記ウィンドウのテキストボックスに文字列
 Hellow World !!をキーインして、Send Dataボタンをクリックする

APIC側キバン(PICDEM相当自作キバン)では、USBケーブル経由送信されてきたたこの文字列を受信した後、この文字列をRS232Cケーブル経由でRS232C通信でエコーバックする

BPC側ではエコーバックされてきたデータを通信ソフトTera Termで受信し、これをウィンドウに表示する。
                      




      ★全体のハード 及びPIC側のソフト
                 → 全体&PIC側参照


(注)ウィンドウの背景にある画像は、本テーマとは関係ありません

    デモソフト:
        Serial Emulator


送信側(RS232C通信):Tera Term
受信側(USB通信):PICDEMサンプルソフト


@Tera Term(注)に Data from TeraTerm とキーイン後、エンターキーを押しRS232C経由でPIC側(PICDEM相当)にデータを送信する。
APIC側では受信データをそのままUSBケーブル経由でPC側に送信する。
BPC側ではPICDEMデモソフトの右記ウィンドウのリッチテキストボックスで受信データを表示する。


      ★全体のハード 及びPIC側のソフト
                 → 全体&PIC側参照

(注)TeraTermのローカルエコーがONであるのでキーインしたデータが表示されている。



■ PIC18 CDCクラス 通信 (液晶付き) 
  マイクロチップ社のMCHPFSUSB Framework 2.3をダウンロードすると入手できる公開ソフトをベースに設計した、PCとPIC18F4550間のUSB通信(CDCクラス 液晶付)の例を紹介します。 ハード 及びPIC側のソフトは こちらを参照願います 
            

<試作品仕様>
 ・PC側からデータをPIC側にUSB CDCクラス通信で送信する。
 ・PIC側では受信した文字列を液晶上段に、受信データに基づき返信したデータを液晶下段に表示する。
 ・PC側でも受信したデータをテキストボックスに表示する。
 ・PC側からの送信データ 及びPIC側からの返信データは以下とする。
     @ How are you ?     →  I am fine !!
     A Your name ?      →  My name is PIC
     B This is a pen      →  Pardon?                 

   <プログラム>


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;      //要追加

namespace USB_LCD_Shift_Jis
{
    public partial class Form1 : Form
    {
        //文字を変換するクラスを宣言
        Encoding encSjis = Encoding.GetEncoding("shift-jis");
        Encoding encUni = Encoding.GetEncoding("unicode");

       delegate void SetTextCallback(string text);//デリゲート宣言
   
    

     
            




        public Form1()
        {
            InitializeComponent();
           
            UpdateCOMPortList();    //使用可能COMポートリストチェック

            SendData_ComboBox.Items.Clear();
            SendData_ComboBox.Items.Add("How are you ?   ");
            SendData_ComboBox.Items.Add("Your name ?     ");
            SendData_ComboBox.Items.Add("This is a pen   ");
            SendData_ComboBox.SelectedIndex = 0;        //コンボボックス選択値の初期値設定 

        }

        private void UpdateCOMPortList()    //使用可能COMポートチェック & リスト作成
        {
            int i;
            bool foundDifference;

            i = 0;
            foundDifference = false;

            if (Port_comboBox.Items.Count == SerialPort.GetPortNames().Length)
            {
                foreach (string s in SerialPort.GetPortNames())
                {

                    if (Port_comboBox.Items[i++].Equals(s) == false)
                    {
                        foundDifference = true;
                    }
                }
            }
            else
            {
                foundDifference = true;
            }

            if (foundDifference == false)
            {
                return;
            }

            Port_comboBox.Items.Clear();
            foreach (string s in SerialPort.GetPortNames())
            {
                Port_comboBox.Items.Add(s);
            }
            Port_comboBox.SelectedIndex = 0;
        }

  

        private void CloseBtn_Click(object sender, EventArgs e)
        {
            CloseBtn.Enabled = false;
            ConnectBtn.Enabled = true;
            Port_comboBox.Enabled = true;

            try
            {
                serialPort1.DiscardInBuffer();  //入力バッファーのデータ破棄
                serialPort1.DiscardOutBuffer(); //出力バッファーのデータ破棄

                serialPort1.Close();
            }
            //If there was an exeception then there isn't much we can
            //  do.  The port is no longer available.
            catch { }

        }

   
        private void timer1_Tick(object sender, EventArgs e)    //COMポートの周期的チェック&更新
        {
            UpdateCOMPortList();
        }

        private void ConnectBtn_Click_1(object sender, EventArgs e)
        {
            try
            {
                serialPort1.PortName = Port_comboBox.Items[Port_comboBox.SelectedIndex].ToString();

                serialPort1.Open();  //COMポートオープン

                ConnectBtn.Enabled = false;
                Port_comboBox.Enabled = false;
                CloseBtn.Enabled = true;

                Receive_textBox.Clear();
                Receive_textBox.AppendText("Connected.\r\n");
            }
            catch   // COMポートが開けない場合
            {
                CloseBtn_Click(this, null);
            }
        }

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)     //受信
        {
            try
            {
                byte[] byteRead = new byte[serialPort1.BytesToRead];  //受信文字

                serialPort1.Read(byteRead, 0, serialPort1.BytesToRead);//shift-JIS読み込み
                byte[] byteUni = Encoding.Convert(encSjis, encUni, byteRead);   //shift-JIS からunicodeに変換する
                string strUni = encUni.GetString(byteUni);  //配列を文字列に変換

                SetTextCallback SetTextCallback = new SetTextCallback(SetText);
                this.Invoke(SetTextCallback, strUni);


            }
            catch
            {
                //If there was an exception, then close the handle to 
                //  the device and assume that the device was removed
               CloseBtn_Click(this, null);
            }

        }

        private void SetText(string text)   //受信スレッドからメインスレッドへの書き出し
        {
            if (Receive_textBox.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                Invoke(d, new object[] { text });
            }
            else
            {
                //If this function was called from the same thread that 
                //  holds the required objects then just add the text.
                Receive_textBox.AppendText(text);
            }
        }

        private void SendBtn_Click_1(object sender, EventArgs e)    //送信
        {
            try
            {
                string strSend = SendData_ComboBox.Text;
                if (!strSend.EndsWith("\r")) strSend += "\r";  //改行が無かったら \rを追加する
                serialPort1.Write(strSend);
            }
            catch
            {
                //If there was an exception, then close the handle to 
                //  the device and assume that the device was removed
                CloseBtn_Click(this, null);
            }

        }

    }

       
  
}

<動作結果>
 @ PC側のウィンドウから仮想COM8ポートを選択してを接続ボタンをクリックする。
 A USB接続が完了して受信データテキストボックスに Connected が表示される。
 B 送信データ用コンボボックススから How are you ? を選択して送信ボタンをクリックする。
 C PIC側で受信した受信データ How are you ? が液晶の上段に表示されています。
 D 返信データとして I am fine !! がプログラムで選択され、これを液晶下段に表示されています。また、同時にPC側にも送信されています。
 E この結果、PC側では 受信したデータ I am fine !! を受信データ用テキストボックスに表示しています。
 F 同様に Your name ?  を送信した場合 My name is PIC が返信された場合も表示されています。
 G 同様に This is a pen  を送信した場合 Pardon? が返信された場合も表示されています。
 

PC側 
送受信ウィンドウ
PIC側 液晶画面



■ PIC32MZ - PC間 CDCクラス ASCII文字列の送受信(キャラクタ液晶、Harmony)


PIC32MZ2048ECH144にキャラクタ液晶を接続した HarmonyによるCDCクラスのUSB通信 送受信の例を紹介します。   → PIC側  ソフト
   
  <試作品仕様>
    ・PCとPIC32MZ間で 文字列の送受信をおこなう。
    ・USBのライブラリはHarmonyのCDCクラスをつかうこと
    ・PC側から文字列に対して PIC側からそれぞれに対応した文字列を返信すること
     送受信の文字列は 以下とする
      PCからの送信文字列            PICからの返信文字列
      Japan\r               Tokyo    
      America\r              Washington
      U.K.\r                London
      France\r              Paris
    ・PICにはキャラくタ液晶を接続し 受信文字列と返信文字列を表示すること
    ・PIC側のダイアログのテキストボックスに受信文字列を表示のこと
    ・ 開発環境  PIC側: Harmony ver. 1.03   XC32 ver.1.34  MPLABX ver.2.35  PIC32MZ2048ECH144 revision 5
              PC側: VC# 2012


        プログラム 
   

   

          

   




using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace Kanji_PC_PIC { public partial class Form1 : Form { //文字を変換するクラスを宣言 Encoding encSjis = Encoding.GetEncoding("shift-jis"); Encoding encUni = Encoding.GetEncoding("unicode"); public Form1() { InitializeComponent(); serialPort1.PortName = "COM3"; //COM1 ポート使用 serialPort1.BaudRate = 9600; //9600bps serialPort1.Parity = System.IO.Ports.Parity.None; //パリティなし serialPort1.DataBits = 8; //データ長 8ビット serialPort1.StopBits = System.IO.Ports.StopBits.One; //ストップビット 1 serialPort1.ReadTimeout = 500; //500mse 読み込みタイムアウト時間 serialPort1.WriteTimeout = 500; //500msec書き込みタイムアウト時間 comboBox1.Items.Clear(); comboBox1.Items.Add("Japan"); comboBox1.Items.Add("America"); comboBox1.Items.Add("U.K."); comboBox1.Items.Add("France"); // comboBox1.Items.Add("I_am_fine"); comboBox1.SelectedIndex = 0; } delegate void ReceiveDelegate(string str);//デリゲート宣言 private void SetText(string str) { richTextBox1.AppendText(str); } private void button1_Click(object sender, EventArgs e) { if(serialPort1.IsOpen == false)serialPort1.Open();//シリアルポートオープン string strSend = comboBox1.Text; if (!strSend.EndsWith("\r")) strSend += "\r"; //改行が無かったら \rを追加する Byte[] byteArry = encSjis.GetBytes(strSend); //'送信文字をShift-jisに変換してをByte配列に格納 serialPort1.Write(byteArry, 0, byteArry.Length); //送信 } private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { byte[] byteRead = new byte[serialPort1.BytesToRead]; //受信文字 serialPort1.Read(byteRead, 0, serialPort1.BytesToRead);//読み込み byte[] byteUni = Encoding.Convert(encSjis, encUni, byteRead); //shift-jis からunicodeに変換する string strUni = encUni.GetString(byteUni); //配列を文字列に変換 ReceiveDelegate receiveDelegate = new ReceiveDelegate(SetText); this.Invoke(receiveDelegate, strUni); } private void button2_Click(object sender, EventArgs e) { richTextBox1.Clear(); } private void button3_Click(object sender, EventArgs e) { serialPort1.Close(); } } }




 <動作結果>

   PIC側液晶画面
上段: 受信文字列
下段: 返信文字列
PC画面 
送信前     
 PCから "Japan\r"を
送信した場合
   
 PCから 以下の順番で
文字列を送信した場合
"Japan\r"
"America\r"
"U.K.\r"
"France\r"