PICのUSBホスト機能を動かしてみる(CDC-Basic編)

〔MSD-HOST編〕 〔USBデバイス編〕 〔マイコンのトップに戻る〕


以前にPIC18F14K50を使いこちらでUSBのデバイス側の実験は行っています。
今度はPIC24FJ64GB002を使いUSBのホスト側の実験を行って見たいと思います。
行う実験は、CDCクラスでUSARTの様にシリアル通信をやって見ます。
尚、24FJ64GB002はホスト動作の他に、デバイス動作も出来て、OTG(On The Go)も出来る様です。
又、OTGの話は週刊アスキーさんのこちらを参考にして下さい。

最新のMLA"v2018-11-26"バージョンを使いたかったのでダウンロードしたがインストール出来ない、
なので以前インストールして置いた"v2016-11-07"バージョンを使う事にしました。
MLAのUSBフレームワークのインストール等については、こちらを参照下さい。

《USBデバイス側の話》

デバイス側で使用するPICは18F14K50で秋月電子のUSB対応超小型マイコンボードです、
USBで利用する為の部品が全て実装されているので便利に使用出来ます。

CDCクラスでパソコンとデータの送受信を行う」の以前の実験で使用したソフトをそのまま入れて
PCで動作したので、デバイスとしてホスト(24FJ64GB002)に接続し動作させたのですがぁ...
動かない!
エニュメレーションは正常に終わり、その後の送受信タスクまでたどり着けない!
散々、あーだぁ、こーだぁ、格闘する事まるまる4日、もうダメ、次のトライがダメなら諦めますです。

次のトライとは、
MLA"v2016-11-07"バージョンのUSBフレームワークで
"C:\microchip\mla\v2016_11_07\apps\usb\device\cdc_basic\firmware\
low_pin_count_usb_development_kit_pic18f14k50.x
"これを使います。
結果は動作しました、これでぇ次に進めますがぁ精魂尽き果てました。

”low_pin_count_usb_development_kit_pic18f14k50.x”の動作は、
・ホストから受信したデータに+1をしてホストに送り返えします。("A"なら+1するので"B"で送信)
・RA3に接続したスイッチを押せばホストに”Button pressed.\r\n”とメッセージを送信します。

でえ、変更した点は、
・"app_device_cdc_basic.c"のボーレートを[9600]から[19200]に変更しました。
・USB対応超小型マイコンボードの場合は、RA3(MCLR)ピンでありちょっとぉ使いづらい。
 他のピンに変更できたのだがぁ、"精魂尽き果てた"ので止めてぇスイッチ入力は無効とした。

↓から変更した分のファイル(app_device_cdc_basic.c)のみダウンロード出来ます。
app_device_cdc_basic.zip

ダウンロードファイルは、”low_pin_count_usb_development_kit_pic18f14k50.x”のファイルと
入れ替えてからコンパイルしましょう。
MPLAB X V4.10MPLAB(R) XC16 C Compiler Version 1.30コンパイラで行っています。

以上をコンパイルし書き込みましょう、電源はバスパワー(USBから得る)としました。
尚、このデバイスをPCに繋ぎ"TeraTerm"等で動作する事を確認して置きましょう。

《USBホスト側の話》

ホスト側で使用するPICは24FJ64GB002を使用しました。
(今回のプログラムをコンパイルすると50%:32Kなのでぇ、24FJ32GB002は無理でしょう)

使ったプログラムは、
MLA"v2016-11-07"バージョンのUSBフレームワークで
"C:\microchip\mla\v2016_11_07\apps\usb\host\cdc_basic\firmware\
exp16_pic24fj64gb004_pim.x
"これを使います。

”exp16_pic24fj64gb004_pim.x”の動作は、
・データの送受信が出来る状態になるとLEDが点灯します。
・デバイスからデータを受信するとLCD表示器に内容を表示します。
 (ホストからのデータ送信は有りません)

でえ、変更した点は、
・先ずは、24FJ64GB004用なので24FJ64GB002用にプログラムを変更しました。
・エニュメレーションの実行状態を確認する為のLEDを追加しました。
 (デバイス接続時の"EVENT_ATTACH"を追加)
・表示をUARTに変更しPCの"TeraTerm"等で確認できる様に変更しました。
・"TeraTerm"からデータを受けたらそれをデバイスに送信する機能を追加しました。

USB(OTG)のPIC24Fファミリー・日本語リファレンスマニュアルはこちらを参照下さい。

(USBホストのファイルについて)

↓からUSBホストで使用したデモプログラムをダウンロード出来ます。
host_CDC_Basic.zip

ダウンロードファイルはMPLAB Xのプロジェクトファイルの形で提供しますので
そのまま利用出来ると思います。
但し、MPLAB X V4.10MPLAB(R) XC16 C Compiler Version 1.30コンパイラで行っています。

下記ファイルがUSBホスト側で使用するCDCクラスのプログラム一覧です。




CDC.c
CDCクラスのメインデモプログラムです。
app_host_cdc_basic.c
app_host_cdc_basic.h
USB(CDC)で送受信を行う為のアプリ側サンプルプログラムです。
skUART.c
skUART.c
UART通信を行うドライバです。
PCとUSBシリアル通信を行います。
このファイルの使い方等は、こちらを参照下さい。
skDEBUG.c
skDEBUG.c
"usb_host_cdc.c"と"usb_host.c"プログラムに組み込まれている
デバッグ表示機能をONにしたい場合に使用します。
"usb_host_cdc.h"の #define DEBUG_MODE を生かします。
"usb_config.h"の #define DEBUG_ENABLE を生かします。
usb_config.c
usb_config.h
USB組み込みホスト用の周辺機器設定リスト(TPL)の定義と
USBの構成を設定する機能を提供します。
ボーレート等の通信回線情報もここで設定されています。
C
D
C
クライアント層
usb_host_cdc_interface.c
usb_host_cdc_interface.h
アプリケーション層がCDCクライアントドライバにアクセスする為のインタフェース機能を提供します。

usb_host_cdc.c
usb_host_cdc.h
USB組み込みホストにCDCクラスのサポートを提供します。





U
S
B
組込み
ホスト

usb_host.c
usb_host.h
全てのデバイスに対してUSB組み込みホストドライバ
サポートを提供します。
クラスサポートは提供しません。
usb_hal_pic24.c
usb_hal_pic24.h
PIC24Fコアをスリープ状態にして、USBアクティビティで
デバイスを起動する様にUSBモジュールを設定します。
usb.h
usb_ch9.h
usb_common.h
usb_hal.h
usb_hal_local.h
usb_host_local.h
usb_struct_queue.h
その他のUSBサポートヘッダファイル

赤色ファイルが、プログラムの変更及び改造&ファイル追加を行った物です。
※ 又、プログラム内のコメントを一部日本語化しています。
※ "usb_config.c/usb_config.h"ファイルは"MPLAB X IDE"で開けなかったので、
  "TerPad"で[SHIFT-JIS]で上書き保存を行ったところ開ける様になりました。

ヒープ領域

USB組み込みホストスタックは、メモリ空間を動的(ダイナミック)にメモリの割り付けと解放を行う様に
プログラミングされています、なのでヒープ領域を割り当ててやらないとエラーが出ます。

ヒープ領域の割り当て画面
IDEのプロジェクトプロパティを開き、"xc16-ld"をクリックし、オプション画面を表示させます。
オプションカテゴリは"General"で"Heap size"の項で"2000"程入力しましょう。
但し、この操作はMPLAB X v4.10でXC16 v1.30時での操作となります。
でもぉ、今回はプロジェクトファイルで提供するので設定は出来ているはずです。
"ヒープ領域"と"メモリの割り付けと解放"の記事はこちらを参照して下さい。

その他に以下の資料も参考にしています。
・USB Embedded Host Stack Programmers Guide(AN1141)
・USB 組み込みホストスタック(AN1140)
・Communication Device Class (CDC) Host(AN1247)
USB Library Help

(USBホストの回路について)

USBホストの回路
回路の電源は3.3Vで、USBのVBUS用電源が5.0Vなので両電源を用意する必要が有ります。
PICの内蔵レギュレータ用に、"10uF/16V low-ESR capacitor"ですが
無いので電解コンデンサを使いました。
又、VBUSを安定化させる電解コンデンサ150uFも持っていないので100uFで行っています。

超小型USBシリアル変換モジュール
PICのUART通信をUSBでPCに接続してくれるモジュールです、
モジュールのピンは図左側から[5V][GND][TXD][RXD]の順で、[5V]ピンは使用しません。
このモジュールの少し詳しい話は、こちらを参照下さい。

USBコネクタDIP化キット(Aメス)
USB-TypeA(メス)コネクタをブレッドボードで使用出来る様にするキットです。
注意は、固定用の半田付けピンが2.54/1.27mmの両方あるのでよぉ〜くぅ見て見て。
無論キットなので半田付け必須です、
最近半田付けがぁチョットぉ辛い、メガネタイプの拡大鏡が欲しいかもぉ (^0_0^)

尚、OTG機能を利用する場合は、”マイクロBメスUSBコネクタDIP化キット”を使いましょう。

(USBホスト回路の動作)

@ "超小型USBシリアル変換モジュール"をPCに接続します。

A PCで"Tera Term"等のシリアル端末を起動させます。(操作方法は省略します)
  ボーレートは"19200bps"に設定して下さい。
  (端末の設定で、ローカルエコーを"ON"にしておいた方が送受信が見れて解り易いでしょう)

B デバイスはまだ接続せずにホスト側の電源を入れます。

C [LED1]が3秒間点灯しPICが起動した事を知らせます。

D さぁ、デバイスを挿して下さい。

E [LED1]が点灯しデバイスの接続を知らせます、デバイスが外れるまでは点灯しています。
  もし、点灯後消灯した場合(もしくは点灯しない)はエニュメレーションが失敗しています。
  エニュメレーションの話は、[picfun(電子工作の実験室)]さんのこちら「USBのプラグ&プレイ」
  参考にしましょう、又、「CDCクラスでパソコンとデータの送受信を行う」も併せて読みましょう。

F 次に[LED2]が点灯し、CDCで送受信の通信が可能になった事を知らせます。
  この[LED2]もデバイスが外れるまでは点灯しています。

G [LED1][LED2]が点灯すれば操作可能です。

H "Tera Term"から文字(キー入力)を送って下さい、その文字をデバイスに送信します、
  送信完了で"Tera Term"に">"を送ります。
  デバイスからは送信した文字+1が帰って来るはずです。
  例えば、キーボードの[A]を押せば、+1されるので[B]が受信されると思います。
  "Tera Term"の表示上は"A>B"となります。

I デバイスをホストから取り外しましょう、[LED1][LED2]が消灯します。
  PCの様にデバイスを安全に取り外すとかは考慮していません。

(転送を実行する関数の説明)

"app_host_cdc_basic.c"ファイル内で使う、CDC転送(送受信)を実行する関数について書いて置きます
デバイスとの通常のCDC通信は、デバイスがエニュメレーションされた後に開始できます。

ans = USBHostCDC_ApiDeviceDetect( )
この機能は、CDCデバイスが接続されていて使用可能かどうかを判断します。
これはデバイスとの通信を待つ間にループで常に呼び出し、タスクが実行されている事を確認します。

 bool ans : true  - CDCが存在し、準備ができている
       false - CDCが存在しない又は準備ができていません

ans = USBHostCDC_Api_Get_IN_Data(no_of_bytes,data)
この機能は、デバイスからデータを受信する為の要求を行います。
デバイスに"IN"トークンパケットを発行します。
これはデバイスからデータを送信させる為に定期的に呼び出さないといけません。

 uint8_t no_of_bytes - デバイスから予想されるバイト数(MAX 64)
 uint8_t* data     - 受信したデータを格納するバッファへのポインタ
 bool   ans :  true  - 転送要求は正常に行われました
          false - 転送要求が失敗しました

※ 定期的に呼び出すが必ずしも1ms毎とかは必要無いです、USBモジュールのハード側が
  "SOFトークン"を1ms毎に送信するのでデバイスはサスペンド状態には移行しないと思います。
  だがしかし余りにも遅いとぉデバイスからの送信データが届くのが遅れますよ。

ans = USBHostCDC_Api_Send_OUT_Data(no_of_bytes,data)
この機能は、デバイスへのデータ送信要求を行います。

 uint8_t no_of_bytes - デバイスから予想されるバイト数
 uint8_t* data     - 送信するデータバッファへのポインタ
 bool   ans :  true  - 転送要求は正常に行われました
          false - 転送要求が失敗しました

ans = USBHostCDC_ApiTransferIsComplete(errorCodeDriver,byteCount)
この機能は、送受信の転送状態を調べる為に呼び出されます。
転送が成功したか如何かを確認するには、返されたエラーコードを確認する必要があります。
最後の転送がIN転送だった場合、byteCountは受信したバイト数を返します。
最後の転送がOUT転送だった場合、byteCountは送信されたバイト数を返します。

 uint8_t* errorCodeDriver - 戻り値(エラーコード)
        USB_SUCCESS         = 正常終了
        USB_CDC_DEVICE_NOT_FOUND = 指定されたアドレスのデバイスは利用できません
        (その他のエラーは"usb_host_cdc_.h"を参照)
 uint8_t* byteCount    - 転送されたバイト数
 bool   ans :   true  - 転送は完了しました
           false - 転送は保留中です

 IN転送での使用例1)
 uint8_t count , data[MAX_NO_OF_IN_BYTES] ;
 uint8_t error ;

 error = USBHostCDC_Api_Get_IN_Data(MAX_NO_OF_IN_BYTES, &data) ;
 if (!error) {
     while (!USBHostCDC_ApiTransferIsComplete (&error, &count)) {
         USBHostTasks() ;
         USBHostCDCTasks();
     }
     if( (error == USB_SUCCESS) && (count != 0) ) {
         // データを受信した、シリアル通信でPCに送る
         UART_Send((char*)data, count) ;
     }
 }

 OUT転送での使用例2)
 uint8_t count , data[MAX_NO_OF_OUT_BYTES] ;
 uint8_t error ;

 memcpy(data,"test",4) ;
 error = USBHostCDC_Api_Send_OUT_Data(4, &data) ; 
 if (!error) {
     while (!USBHostCDC_ApiTransferIsComplete (&error, &count)) {
         USBHostTasks() ;
         USBHostCDCTasks();
     } 
     if( (error == USB_SUCCESS) && (count != 0) ) {
         // 正常に送信完了、シリアル通信でPCに送る
         UART_Send("TransferIsComplete", 18) ;
     }
 }
ans = USBHostCDC_Api_ACM_Request(requestType,size,data)(未実験)
この機能をアプリケーションコードで使用して、ACM(Abstract Control Model)固有の要求に
動的にアクセスする事ができます。
この機能は、アプリケーションが事前に設定されたレートからボーレートを変更しようとしている場合に
のみ使用してください。デバイスとの間で送受信されるデータはバイトの配列です。
アプリケーションはこの機能を使用する前にデータフォーマットを理解する事に特別な注意を払う必要が
あります。

 uint8_t requestType - USB_CDC_SEND_ENCAPSULATED_COMMAND
              (プロトコルで定義された AT コマンド等を送信する)
             - USB_CDC_GET_ENCAPSULATED_REQUEST
              (上で送信したコマンドに対する レスポンスを要求する)
             - USB_CDC_SET_LINE_CODING
              (通信速度・データ長・パリティビッ ト・ストップビット長の設定を行う )
             - USB_CDC_SET_CONTROL_LINE_STATE
              (通信回線制御信号 RTS・DTR の設定を行う)
          (これらは、CDCホストスタックによってサポートされている必須のCDC要求です)
 uint8_t size     - 転送するバイト数
 uint8_t* data      - 転送されているデータへのポインタ。
 uint8_t ans : USB_SUCCESS         - リクエストは正常に開始されました
         USB_CDC_DEVICE_NOT_FOUND - 指定されたアドレスを持つデバイスがありません
         USB_CDC_DEVICE_BUSY    - 転送を実行する為のデバイスが適切な状態でない
         USB_CDC_COMMAND_FAILED  - 要求はサポートされていません
         USB_CDC_ILLEGAL_REQUEST  - 要求されたIDが無効です


《その他》

実験時の写真
実験時の回路写真です、結構シンプルですね。
この写真ではブレッドボードを反対で使っているので、上の実態配線図とは電源が逆です。
USB仕様では、VBUSは5.0VとなっているがPIC18F14K50は2.7-5.5Vの電源で動作するので、
今回の実験でならVBUSを3.3Vに接続しても動作はします。

当初は、HIDクラスも実験対象だったがぁ...."精魂尽き果てた"ので....
それにぃ、マイコンにキーボードはまだしもぉ、マウスぶら下げてぇ何操作するのぉってぇかんじぃ。





【きむ茶工房ガレージハウス】
Copyright (C) 2006-2019 Shigehiro Kimura All Rights Reserved.