STM32F4DiscoのマイクロUSBをHostとしてHIDをつなぐ
STM32F4DiscoのマイクロUSBコネクタはABレセクタブルですのでType A(Host)、Type B(Peripheral)どちらにも使用できます。
今回はHostとして設定してHID(Human Interface Device:マウスやキーボード)をつないでみます。STM32F746DiscoでもいいのですがF4Discoで十分なのでこれを使います。
あとSTM32F4Disco基板側はマイクロUSBですがマウスやキーボードは普通USB TypeAなのでMicroBオス-Aメス USB変換ケーブルが必要です。例えばSANWA AD-USB18とか。
では今回もCubeIDEから作っていきます。実はCubeIDEから作っていくとほとんどデフォルトで基本的な設定が終わっているので少しコードを足すだけで”STM32F4DiscoのマイクロUSBをHostとしてHIDをつなぐ”ができます。
ちなみに私のSTM32CubeIDEは日本語化しているのでメニューの表現が日本語になります。日本語化していない方は日本語⇔英語を読み替えて見てください。
まずSTM32CubeIDEプロジェクトを作ります。
ファイル>新規>STM32 Projectを選択するとTarget Selectionウィンドウが開きます。
Board SelectorタブのBoards ListでSTM32F4DISCOVERYを選択して「次へ」ボタンを押します。
プロジェクト名に適当な名前を入れて(本例ではF4DiscoUSBH_HIDとしています)、「完了」ボタンを押します。
「Board Project Options」ウィンドウに”Initialize all peripherals with their default Mode ?”(すべての周辺機器をデフォルトモードで初期化しますか ? )とでるので「はい」ボタンを押します。
とりあえずプロジェクトができます。
「Connectitivity」→「USB_OTG_FS」を選択してみると既に「Host_Only」がデフォルトです。ちなみにこれを「OTG/Dual_Role_Device」を選択するとUSB部分が殆ど空コードになります。OTGとはOn The Goの事でHostにもPeripheralにもなる規格の事ですがさすがに範囲が広すぎてGUIで設定するのが難しいのでしょうか。
本編ではこのまま「Host_Only」にしておき、続いて「Middleware」→「USB_HOST」で「Class for FS IP」で「Human Interface Host Class(HID)」を選びます。
続いて「ファイル」→「保存」すると「Do you want generate Code?」と聞いてくるので「はい」ボタンを押します。
実はこれでUSB Host機能は概ねできていしまっています。あとはHID(マウスやキーボード)に変化があったときの処理を追記するだけです。
HIDに変化があったときにどの関数が呼び出されるかというと”usbh_hid.c”ファイルの”USBH_HID_Process”関数のcase HID_POLL:内のUSBH_HID_EventCallback(phost);が呼び出されます。
USBH_HID_EventCallback()は「ナビゲート」→「宣言を開く」で辿るとわかるように__weakキーワードが付いているのでmain.cなどにUSBH_HID_EventCallback()を実装します。
このときUSER CODE BEGIN ~ USER CODE END内にコードを書かないとiocファイルを更新したときに綺麗サッパリ消去されてしまいますのでお気を付けを。
元の__weak USBH_HID_EventCallback()は__weakキーボードが付いているのでそのままでいいです。
USBH_HID_EventCallback()での処理はusbh_hid.cにあるUSBH_HID_GetDeviceType()でHIDの種別を識別してそれぞれUSBH_HID_GetKeybdInfo()、USBH_HID_GetMouseInofo()でイベント内容を取得します。
7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
void USBH_HID_EventCallback(USBH_HandleTypeDef *phost) { HID_TypeTypeDef hidType; HID_KEYBD_Info_TypeDef *keybd_info; HID_MOUSE_Info_TypeDef *mouse_info; hidType = USBH_HID_GetDeviceType(phost); if(hidType == HID_KEYBOARD){ keybd_info = USBH_HID_GetKeybdInfo(phost); } else if(hidType == HID_MOUSE){ mouse_info = USBH_HID_GetMouseInfo(phost); } } |
あと先頭の方で#include “usbh_hid.h”の1行を挿入します。
1 2 3 4 |
/* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "usbh_hid.h" /* USER CODE END Includes */ |
とりあえずここまででキーボードやマウスを操作したとき情報が取得できるか確認してみましょう。
「実行」→「デバッグ」を選択すると「起動構成プロパティーの編集」画面が開きます。
STM32F4DiscoとPCをミニUSBケーブルでつなぎ「OK」ボタンを押します。
keybd_infoやmouse_infoはまだ使用していないのでwarningがでますが、とりあえず動作させましょう。
用意した(しているなら)MicroBオス-Aメス USB変換ケーブルを介してキーボードかマウスとSTM32F4Disco基板のマイクロUSBコネクタを接続してから「実行」→「再開」してプログラムを走らせます。
USBH_HID_EventCallbak()関数内にブレークポイントを追加してキーボードかマウスを操作してブレークがかかればOKです。
さらにkeybd_info(HID_KEYBD_Info_TypeDef)、mouse_info(HID_MUSE_Info_TypeDef)に入った情報をデコードして具体的な値に変換します。
mouse_infoはmouse_info->x、mouse_info->yがマウスの移動量(-128~127)、mouse_info->buttons[0]が左ボタン(押されると1)、mouse_info->buttons[1]が右ボタン(押されると1)、mouse_info->buttons[2]がスクロールボタン(押されると1)といった感じで特にデコードする必要はないのですが、keybd_info->keys[0]には例えば”A”を押すと”4″が入ります。
これは何でしょうか。
これはUSB規格のHID Usage TablesのKeyboard Pageの規格で定められているUsageIDです(10 Keyboard/Keypad Page(0x07))。
これをUSBH_HID_GetASCIICode(keybd_info)に渡してASCIIコードが得られます。
これらを見やすいようにuartで送信してserial – USB変換ケーブルを通してパソコンのTeraTermなどで見られるようにしてみましょう。
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
uint8_t asciiCode; uint8_t buttonInfo; hidType = USBH_HID_GetDeviceType(phost); if(hidType == HID_KEYBOARD){ keybd_info = USBH_HID_GetKeybdInfo(phost); asciiCode = USBH_HID_GetASCIICode(keybd_info); HAL_UART_Transmit(&huart2, &asciiCode, 1, 100); } else if(hidType == HID_MOUSE){ mouse_info = USBH_HID_GetMouseInfo(phost); if(mouse_info->buttons[0] == 1){ buttonInfo = 'L'; } else if(mouse_info->buttons[1] == 1){ buttonInfo = 'R'; } else if(mouse_info->buttons[2] == 1){ buttonInfo = 'C'; } HAL_UART_Transmit(&huart2, &buttonInfo, 1, 100); } |
入力された情報をuartで送信しています。
最初、キーボードからabcABCと入力して、その後マウスにつなげかえて左ボタンクリック、右ボタンクリック、スクロールボタンクリックしています。
プロジェクト全体はこちら(GitHub)。