UART to USB HID 変換IC、CH9329の使い方。

# 目的
あらゆるマイコンでキー入力ができるようにするために、CH9329というICをつかってみよう。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3264882/afb91346-3f88-bc06-4369-e449c96c26c8.png" width="400px">
# ICの仕様

## ピン
データシート(https://akizukidenshi.com/download/ds/wch/ch9329.pdf )から引用したピン配置の図を以下に示す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3264882/8a0e63a9-917f-7bd6-c6c5-976469d22d85.png)
今回使用するピンを以下に示す。

|ピン番号 |ピン名称  |機能|
|---|---|---|
|1 |ACT# |ICが動作していることを示す信号を出す。今回はLEDを接続する。|
|2,3,4,5 | MODE0,1　CFG0,1 |動作モードを選択する。内部プルアップとなっている。今回はどちらもHIGHにする(何も繋がない)。|
|8 |RXD  |マイコンからのシリアル信号の入力|
|12,13  | UD+,UD- |USBの信号線。USBコネクタに直接接続する|
|14 |GND  |グランド|
|15 |VCC  |5Vの電源。USBコネクタからここに供給する。動作を安定させるため、パスコンを繋がなければならない。|
|16|V33  |3.3V電源の出力。USBから供給された5Vの信号が内部でレギュレーターで3.3Vに変換される。動作を安定させるため、3.3Vの部品を繋がなかったとしてもここにパスコンを繋がなければならない。  |


# 回路
## 使用部品
|部品名 |型番  |数量|秋月電子通商URL  |
|---|---|---|---|
|UART to USB HID 変換IC  |CH9329  |1|https://akizukidenshi.com/catalog/g/gI-17539/  |
|SSOP16 DIP化基板 (CH9329用) |  |1|https://akizukidenshi.com/catalog/g/gP-06541/  |
|USB microB DIP化基板  |  |1|https://akizukidenshi.com/catalog/g/gP-06541/  |
|PICマイコン  |PIC16F1827  |1|https://akizukidenshi.com/catalog/g/gI-04430/|
|ブレッドボード  |  |1|https://akizukidenshi.com/catalog/g/gP-09257/  |
|ジャンパワイヤ  |  |適量|https://akizukidenshi.com/catalog/g/gP-09257/  |
|抵抗  |33Ω  |1| https://akizukidenshi.com/catalog/e/erd25s |
|抵抗  |470Ω  |1| 同上 |
|抵抗  |10kΩ  |1| 同上 |
|積層セラミックキャパシタ  |0.1μF  |2| https://akizukidenshi.com/catalog/g/gP-10147/ |
|積層セラミックキャパシタ  |10μF  |1| https://akizukidenshi.com/catalog/g/gP-08155/ |
|タクトスイッチ |  |1| https://akizukidenshi.com/catalog/g/gP-09828/ |
|ピンヘッダ  |  |適量| https://akizukidenshi.com/catalog/g/gC-00167/ |
|USBケーブル  |  |1| https://akizukidenshi.com/catalog/g/gC-07607/ |
## 回路図
回路図を以下に示す。５V駆動のマイコンで使う想定である。図中のUARTというラベルがある端子にシリアル信号を入力する。私はここに33Ωのダンピング抵抗を入れると動作が安定した。このICの内部には3.3Vのレギュレーターがあり、内部で3.3V電源を使う。そのため、3.3Vの電源を使わない場合も、キャパシタをV33ピンに繋がないと動作しない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3264882/939340f5-74d2-156b-670b-7ad465c0fcab.png)



# ソフトウェア　
## シリアルで送る信号
キー操作をするとき、CH9329に送る信号は以下の通りである。
```
0x57 0xAB 0x00 0x02 0x08 ckey 0x00 ukey 0x00 0x00 0x00 0x00 0x00 sum
```
ckeyとは、装飾キーが押すかどうか示すバイトである。それぞれのビットが1のとき、以下に示すキーが押される。
|bit7|bit6|bit5|bit4|bit3|bit2|bit1|bit0|
|---|---|---|---|---|---|---|---|
|右Windows|右Alt|右Shift|右Ctrl|左Windows|左Alt|左Shift|左Ctrl|

ukeyとは、押すキー(装飾キー以外)のキーコードにする。
sumとは、チェックサムで、全てのバイトの合計の下8ビットにする。

この信号を送ると、キーはずっと押されたままとなる。キーが押されていない状態に戻すには、ckey,ukeyを0x00とした信号を送信すればよい。

シリアルで送る信号については以下の同人誌に詳しくまとまっている。私もこれを参考にした。
https://techbookfest.org/product/iaTanH0UsU9j5TPnFT44rF?productVariantID=4Q1yNxZMFWWs9UJbkx7c6b

## ソースコード
私は以下のようなソースコードを書いた。スイッチを押すと```Hello,World!!```と表示される。
```C
void main(void) {
	while(1) {
		// Add your application code
		while(SW_GetValue() == 1)
			;
		press1key(0x02, 0x0B);		  // Lshift + h
		press1key(0x00, 0x08);		  // e
		press1key(0x00, 0x0F);		  // l
		press1key(0x00, 0x0F);		  // l
		press1key(0x00, 0x12);		  // o
		press1key(0x00, 0x36);		  // ,
		press1key(0x00, 0x1A);		  // w
		press1key(0x00, 0x12);		  // o
		press1key(0x00, 0x15);		  // r
		press1key(0x00, 0x0F);		  // l
		press1key(0x00, 0x07);		  // d
		press1key(0x20, 0x1E);		  // Lshift + 1!
		press1key(0x20, 0x1E);		  // Lshift + 1!
		while(SW_GetValue() == 0)
			;
	}
}
void sendKeyPacket(uint8_t ckey, uint8_t ukey) {
	uint8_t sum		   = 0x10C + ckey + ukey;
	uint8_t packet[14] = {0x57, 0xAB, 0x00, 0x02, 0x08, ckey, 0x00,
						  ukey, 0x00, 0x00, 0x00, 0x00, 0x00, sum};
	for(int i = 0; i < 14; i++) {
		EUSART_Write(packet[i]);
	}
}

void press1key(uint8_t ckey, uint8_t ukey) {
	sendKeyPacket(ckey, ukey);
	//	__delay_ms(1);
	sendKeyPacket(0x00, 0x00);
}
```

```EUSART_Write()```でシリアルに1バイト送信される。
```sendKeyPacket()```でパケットが送信される。1文字送信するには、キーを押すパケットを送信したのち、キーを離すパケットを送信する必要がある。そのため、```press1key()```その両方を行い、1文字だけ入力される。
このあたりは使うマイコンボード、作りたいものに合わせて変えてください。

# まとめ
CH9329を使ってキー入力をすることができた。