STM32F103C8T6でUSB HIDを実装

## はじめに
通称Blue PillとよばれているSTM32F103C8T6ボード。AliexpressではU$1.7程度で売っているST Microの32bit RISCプロセッサ基板。Arduino Microと勘違いして購入してしまい、放置していたものをUSB HIDとして有効活用してみることにした。格安でUSB HIDを実装できることを確認したので、その手順を公開しようと思います。


## 用意するもの - ハードウェア
1. STM32F103C8T6
![HTB1PemDJpXXXXXHXpXXq6xXFXXXM.jpg](https://qiita-image-store.s3.amazonaws.com/0/211703/aae20cba-dd26-ba07-927e-93ad6e86b0c5.jpeg)
2. ST-LINK V2
プログラマです。これがないとプログラム書き込みできません。(無くてもできるようですが有ったほうが便利です。やすいし)
![IMG_9703-800.JPG](https://qiita-image-store.s3.amazonaws.com/0/211703/92fa5884-6c89-6503-643f-4ea8e7387241.jpeg)

## 用意するもの - ソフトウェア
3. System Workbench for STM32<BR>
開発環境です。いろいろ有るようですが私はこれを使用しました。
4. STM32CodeMx<BR>
雛形コードジェネレータです。すごく便利。無くても良いです。
5. STM32 ST-LINK Utility<BR>
ST-LINK V2用のソフトウェアです。プログラム書き込み時に使用します。

個々の入手方法使用方法はぐぐってください。

## STM32CubeMXでコード生成する
![Clipboard02.png](https://qiita-image-store.s3.amazonaws.com/0/211703/df12baa3-9ea3-01ec-5634-a43fd88a910f.png)
New Projectをクリック

![Clipboard03.png](https://qiita-image-store.s3.amazonaws.com/0/211703/f55a249e-6c97-914d-dab0-a3f6919aadcf.png)
STM32F103C8で検索し、Start Projectをクリック
![Clipboard04.png](https://qiita-image-store.s3.amazonaws.com/0/211703/39700314-75be-a176-c183-23e16d8fac7e.png)
1. USB Device(F5)をチェック
2. USB_DEVICEでHIDを選択
3. RCCでCrystal/Ceramicを選択
![Clipboard05.png](https://qiita-image-store.s3.amazonaws.com/0/211703/d62775f5-8f2d-8298-d58b-31a972681d3a.png)
クロック設定はこのように。

![Clipboard06.png](https://qiita-image-store.s3.amazonaws.com/0/211703/f9be8de0-bf2d-2c6c-c703-53f7930f0213.png)
コードを出力します。このとき"Toolchain / IDE"をお使いの開発環境に合わせることを忘れずに!

これで基本コードの生成は完了です。


## System Workbenchでコード編集&コンパイルする
![Clipboard08.png](https://qiita-image-store.s3.amazonaws.com/0/211703/8af9efab-d5aa-51ed-d592-2bfa18e8cab3.png)
File->Importで先程生成のコードをインポートします。Existing Projects into Workspaceを選択してください。

![Clipboard12.png](https://qiita-image-store.s3.amazonaws.com/0/211703/3192f310-979b-3f84-b505-5ac6ab88ff55.png)
キーボードのHIDとするため、修正を加えます。HID_EPIN_SIZEを5に、HID_MOUSE_REPORT_DESC_SIZEを78に。
![Clipboard13.png](https://qiita-image-store.s3.amazonaws.com/0/211703/0e8f858e-7d33-b52a-dc47-1ab3b5452db6.png)
HID_MOUSE_ReportDescをキーボード向けに書き換えます。
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE]  __ALIGN_END =
{
		  // 78 bytes
		  0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
		  0x09, 0x06,        // Usage (Keyboard)
		  0xA1, 0x01,        // Collection (Application)
		  0x85, 0x01,        //   Report ID (1)
		  0x05, 0x07,        //   Usage Page (Kbrd/Keypad)
		  0x75, 0x01,        //   Report Size (1)
		  0x95, 0x08,        //   Report Count (8)
		  0x19, 0xE0,        //   Usage Minimum (0xE0)
		  0x29, 0xE7,        //   Usage Maximum (0xE7)
		  0x15, 0x00,        //   Logical Minimum (0)
		  0x25, 0x01,        //   Logical Maximum (1)
		  0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
		  0x95, 0x03,        //   Report Count (3)
		  0x75, 0x08,        //   Report Size (8)
		  0x15, 0x00,        //   Logical Minimum (0)
		  0x25, 0x64,        //   Logical Maximum (100)
		  0x05, 0x07,        //   Usage Page (Kbrd/Keypad)
		  0x19, 0x00,        //   Usage Minimum (0x00)
		  0x29, 0x65,        //   Usage Maximum (0x65)
		  0x81, 0x00,        //   Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
		  0xC0,              // End Collection
		  0x05, 0x0C,        // Usage Page (Consumer)
		  0x09, 0x01,        // Usage (Consumer Control)
		  0xA1, 0x01,        // Collection (Application)
		  0x85, 0x02,        //   Report ID (2)
		  0x05, 0x0C,        //   Usage Page (Consumer)
		  0x15, 0x00,        //   Logical Minimum (0)
		  0x25, 0x01,        //   Logical Maximum (1)
		  0x75, 0x01,        //   Report Size (1)
		  0x95, 0x08,        //   Report Count (8)
		  0x09, 0xB5,        //   Usage (Scan Next Track)
		  0x09, 0xB6,        //   Usage (Scan Previous Track)
		  0x09, 0xB7,        //   Usage (Stop)
		  0x09, 0xB8,        //   Usage (Eject)
		  0x09, 0xCD,        //   Usage (Play/Pause)
		  0x09, 0xE2,        //   Usage (Mute)
		  0x09, 0xE9,        //   Usage (Volume Increment)
		  0x09, 0xEA,        //   Usage (Volume Decrement)
		  0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
		  0xC0,              // End Collection
};

### キーコード送出のコードを書きます。
![Clipboard14.png](https://qiita-image-store.s3.amazonaws.com/0/211703/a656ea17-e740-7e0a-1fe4-ce3640b44b4e.png)
![Clipboard15.png](https://qiita-image-store.s3.amazonaws.com/0/211703/1e30f875-b10b-df08-2316-dcc6204f045a.png)
"N"を1秒毎に送出するコードです。
キーコードは**アスキーコードではありません**。こちらの[キーコード表](http://www.usb.org/developers/hidpage/Hut1_12v2.pdf)を参照してください。53ページにあります。

![Clipboard18.png](https://qiita-image-store.s3.amazonaws.com/0/211703/1cb5082e-3f81-c79e-fe36-ed7446e3f0ab.png)
ハンマーマークのアイコンをクリックしてコンパイルします。
エラーが発生しなければコンパイルは完了します。

## 書き込み
ST-LINKと接続します。
![IMG_20171105_100846.jpg](https://qiita-image-store.s3.amazonaws.com/0/211703/eab75c25-acd3-1f01-ba5f-74eeca96b946.jpeg)
BOOT0のジャンパーを1にセットして、リセットボタン押下します。
ジャンパーコネクタが小さいので、写真ではケーブルにしています。

STM32 ST-LINK Utilityを起動し、Ctrl+Pを押下。ここでエラーが発生する場合は、上記ジャンパを設定忘れか、リセット忘れです。
![Clipboard20.png](https://qiita-image-store.s3.amazonaws.com/0/211703/fe459a22-e7ce-eca7-1f36-80b0cc1a969b.png)
Browseを押下して、先程コンパイルしたファイルを選択します。プロジェクトフォルダのDebugもしくはReleaseフォルダのしたに.binというファイルがありますので、それを選択。
**重要** Browseによるファイル選択は書き込みの度におこなってください。コード修正したのに書き込み後の動作かわらないということが発生します。

![Clipboard22.png](https://qiita-image-store.s3.amazonaws.com/0/211703/cacee509-f33f-e803-e81b-5db767200152.png)
Startを押下して書き込みます。

## 実行
**BOOT0のジャンバを0に戻しリセットボタン押下**すれば、プログラムが実行されます。
今回はHIDでキーボード仕様のため、USBケーブルを接続することでキー入力が生成されます。
プログラムの例ではNキーを1秒毎に入力されるのが分かるはずです。
![Clipboard23.png](https://qiita-image-store.s3.amazonaws.com/0/211703/af82e80c-f96a-a9e7-e2f7-c4ebccf62e32.png)



## おわりに
STM32F103C8T6でHIDを実現するための資料がなかったので作成しました。参考になれば幸いです。

## Special Thanks!
大変参考になったサイトです。[STM32 - Custom USB HID device step by step](https://notes.iopush.net/stm32-custom-usb-hid-step-by-step-2/)



Ikeda