TOP > MPLAB C18編(PIC18F4550) > USBでパソコンと通信(CDCクラスを使う、プログラムを変更する)

USBでパソコンと通信
(CDCクラスを使う、プログラムを変更する)

更新日2010.2.14


USBフレームワークのCDCクラスを使ってパソコンとUSB接続する実験を行います。
使用するPICはPIC18F4550です。
前のページでは、サンプルプログラムをそのまま動かしましたが、今回は手を加えてみます。

このページの内容
・回路図
・サンプルプログラムの構成
・サンプルプログラムのソース
・サンプルプログラムを改造する
 仕様
 プログラムの改造
 プロジェクトのビルド
・動作確認
 PICにプログラムを書き込みPCに接続
 PC側のハイパーターミナルを起動し動作確認
・プログラミング上の注意事項


回路図

回路は前回と同じです。

こちらは、ブレッドボードに組んだ状態です。

サンプルプログラムの構成

サンプルプログラムのプロジェクトには多くのソースが含まれますが、今回手を加えるソースは「main.c」です。
「main.c」そのものも大きなプログラムですが、関連する関数は下表の黄色の関数です。
ソース関連する関数
main.cmain()InitializeSystem()UserInit()
USBDeviceInit()
ProcessIO()
UserInit() は、電源ON時に1回だけ呼び出されますので初期処理を記述します。
ProcessIO() は、main()のループから毎回呼び出されます。ここには、USBの送受信処理とそれに関わる処理を記述します。


サンプルプログラムのソース

それではサンプルプログラムのソースがどうなっているか見てみましょう。

以下のプロジェクトを開きます。

プロジェクトには多くのソースが含まれています。
「USB Stack」や「Common」フォルダ(下図では開いていませんが)配下にはUSBフレームワークのソースがたくさんあります。(今回はそのまま使います)
Source Filesの下にある main.c を開きます。

main.c main() は以下のようになっています。
最初に、InitializeSystem() を呼び出し、
whileループの中で、毎回 ProcessIO() を呼び出しています。

メインループから毎回呼び出される ProcessIO() の前半は以下のようになっています。
ここでは、sw2(RB4)の状態をチェックし、スイッチが押されていたらUSB通信で「Button Pressed」と言う文字列をパソコンに送信しています。

ProcessIO() の後半は以下のようになっています。
ここでは、USB通信でパソコンから送られてきた文字列(USB_Out_Buffer)の各文字(バイト)に+1して(USB_In_Buffer)パソコンに送り返しています。

前のページで行った実験結果と、PIC側のプログラムの作りが繋がったかと思います。


サンプルプログラムを改造する

それでは、サンプルプログラムをベースにして他の動作をするプログラムを作りましょう。

仕様

新たに作るプログラムの仕様は次の通りです。
パソコン側はWindowsに添付されているハイパーターミナルを使います。

パソコンからのコマンドで、PIC側のRD2,3のLEDを制御します。
コマンドは以下のように6種類としました。
コマンドRD2のLEDRD3のLED
ON3ON-
ON4-ON
OFF3OFF-
OFF4-OFF
ALLONONON
ALLOFFOFFOFF
  '-' は前の状態を維持することを示す
例えば、パソコン側のハイパーターミナルで、ON3[Enter]と入力すると、PIC側のRD2のLEDを点灯します。
PIC側では、Enterキーのコード(0x0d)を受信した時に、それまで受信した文字列とコマンドを比較し、コマンド文字列に該当しない場合は無視します。
例えば、以下のような場合は無視します。
OON3[Enter]
allon[Enter]
ALLONALLOFF[Enter]

プログラムの改造

作業領域の確保
PCから受信したデータがコマンド文字列に該当するかを判断するために、受信データの格納領域とそのインデックスを定義します。
この領域は、CR(0x0d)を受信した時にコマンド文字列と比較して対応する処理を行います。
処理終了後にインデックスをクリアします。

config定義の少し後に2行を追加します。
(行番号247〜248)

初期処理:UserInit()
初期処理では、作業領域のインデックス(Command_IX)を0クリアします。
(行番号589)
メイン処理:ProcessIO()
前半の sw2 が押された時の処理から、LED3のON/OFF処理をコメントにします。
(行番号633,638)


後半のパソコンから受信した時の処理は以下のように改造します。
(行番号643〜687)


 main.c全体のソースをこちらに置いておきます。


プロジェクトのビルド

main.cの改造が終わったらビルドしてエラーが無いことを確認しておきます。


動作確認

プログラムができましたので動作確認を行います。

PICにプログラムを書き込みPCに接続

ビルドしたhexファイルをPICに書き込みます。
そして、USBでPCに接続します。RD0,1のLEDが交互に点滅すると思います。

PC側のハイパーターミナルを起動し動作確認

続いてパソコン側のハイパーターミナルを起動して、PICとの通信確認を行います。
「スタート〜プログラム〜アクセサリ〜通信〜ハイパーターミナル」でハイパーターミナルを起動します。


以下の「接続の設定」で、名前欄に任意の文字を入れて「OK」ボタンを押します。

接続方法から、PIC通信用のCOMポートを選択します。

「OK」ボタンを押します。

フロー制御を「なし」に変更します。

「OK」ボタンを押します。

以上でハイパーターミナルが起動します。
コマンド入力して、PICのLEDがON/OFFすることを確認して下さい。

今回のコマンド仕様は簡易型になっています。コマンドっぽくするには以下のような仕様でしょうか。
コマンドオペランドLEDの動作
RD2のLEDRD3のLED
ON3ON-
4-ON
ALLONON
OFF3OFF-
4-OFF
ALLOFFOFF
例えば、パソコン側のハイパーターミナルで、ON 3[Enter]と入力すると、PIC側のRD2のLEDを点灯します。


プログラミング上の注意事項

メインループはできるだけ短時間で回す。
USBフレームワークは、メインループの延長で送受信処理などを行っています。
このため、メインループの中で時間がかかる処理を行うとUSB通信が正しく行われない事があり得ます。
LEDを一定間隔で点滅させるような場合は、サンプルプログラムのBlinkUSBStatus()で行っているような方法を採ります。