USBキーボードのキー出力表示
(ホストモード HIDクラス)
(→プロジェクトファイル(Harmony Ver.2.04版 ) ダウンロード)
USBキーボードの各キーの出力を キャラクタ液晶 及びTeraTermに出力表示した例を紹介します。 HarmonyのUSB(ホストモード)
HIDクラスを使っています。 尚、PIC32MZとキャラクタ液晶間はI2C、またPIC32MZとTeraTerm(PC)間はUARTです。 |
<仕様>
・PIC32MZにUSBキーボードを接続して各キーの出力情報をキャラクタ液晶とTeraTermに表示すること。
・接続するキーボードは、日本語109キーボードとする。
・PICに接続するキャラクタ液晶はI2Cインターフェースの液晶とする。
・PIC-PC間のUARTは以下とする。
通信速度:9600bps、データ長:8ビット、パリティ:なし、ストップビット:1、フロー制御:なし
・キャラクタ液晶には下記を表示のこと。
①PIC立ち上がり完了:
1行目: USB device HID
2行目: Keyboard demo
②USB初期化完了:
1行目: Please Connect
2行目: Keyboard !!
③各キーデータ取得時:
1行目: 取得キーコード(0x + 16進数表示) 例: 0x04 0xFFFFFF89
2行目:
図形表示キーの場合: 既定の図形 例: abcd... ABCD... 1234 !"#$<>?\...
機能キーの場合: キーボードに記載してある文字 または機能がわかる文字
例: Esc Kanji(半角/全角 漢字キー) PrintScreen Enter 10key
Enter F1
・TeraTermには下記を実施のこと。
①USB初期化完了: ***Connect Keyboard*** を表示する
②USBキーボードの接続を検出した場合: ---Keyboard Connected--- を表示する。
③図形表示キー: 打鍵されたキーに対応する図形 (例: abcd... ABCD... 1234 !"#$<>?\...)
④メインキーのEnterが打鍵された場合: 改行と復帰を行う
⑤ ④を除く機能キー: キーボードに記載してある文字 または機能がわかる文字(代用文字)を表示すること
(例: Esc Kanji(半角/全角 漢字キー) PrintScreen Enter 10key Enter F1)
<外観>PIC32MZ評価ボード(→購入方法)を使った実験品の外観です。
汎用モジュール評価ボード(段積みボード)には本テーマと関係ない部品が多々実装されています
<キーボード用USBコネクタ接続部の詳細> |
<動作結果>(→ 動画 :1080pのHD動画を見ることができます。)
以下は、サンプルプログラムで使用した各キーのキーコード(keyCode)一覧表です。 尚、灰色のセルはサンプルプログラム
(Harmony v.2.04のライブラリ)の中の変数keyCodeでは呼び出せなかったキーです。
下表のキーボードは日本語109キーボードです。 英語101キーボードをはじめキーボードにはたくさんの種類があります。キーボードにより
キーコードはかなり異なるので他のキーボードを使用する場合は注意が必要です。
キーボード(本体)部 | テン キーパッド部 | ||||||||||
キーの 文字 記号 呼称 |
keyCode | キーの 文字 記号 呼称 |
keyCode | キーの 文字 記号 呼称 |
keyCode | キーの 文字 記号 呼称 |
keyCode | キーの 文字 記号 呼称 |
keyCode | キーの 文字 記号 呼称 |
keyCode |
A | 0x04 | 1 | 0x1E | F1 | 0x3A | Menu | 0x65 | Alt Left | 0xE2 | / | 0x54 |
B | 0x05 | 2 | 0x1F | F2 | 0x3B | _ | 0xFFFFFF87 | Alt Right | 0xE6 | * | 0x55 |
C | 0x06 | 3 | 0x20 | F3 | 0x3C | カタカナ ひらがな ローマ字 |
0xFFFFFF88 | Ctrl Right | - | 0x56 | |
D | 0x07 | 4 | 0x21 | F4 | 0x3D | \ | 0xFFFFFF89 | Ctrl Left | + | 0x57 | |
E | 0x08 | 5 | 0x22 | F5 | 0x3E | 変換 | 0xFFFFFF8A | Shift Right | Enter | 0x58 | |
F | 0x09 | 6 | 0x23 | F6 | 0x3F | 無変換 | 0xFFFFFF8B | Shift Left | 1 | 0x59 | |
G | 0x0A | 7 | 0x24 | F7 | 0x40 | Windows Right |
2 | 0x5A | |||
H | 0x0B | 8 | 0x25 | F8 | 0x41 | Windows Left |
3 | 0x5B | |||
I | 0x0C | 9 | 0x26 | F9 | 0x42 | 4 | 0x5C | ||||
J | 0x0D | 0 | 0x27 | F10 | 0x43 | 5 | 0x5D | ||||
K | 0x0E | Enter | 0x28 | F11 | 0x44 | 6 | 0x5E | ||||
L | 0x0F | Escape | 0x29 | F12 | 0x45 | 7 | 0x5F | ||||
M | 0x10 | Back Space | 0x2A | Print Screen | 0x46 | 8 | 0x60 | ||||
N | 0x11 | Tab | 0x2B | Scroll Lock | 0x47 | 9 | 0x61 | ||||
O | 0x12 | Space Bar | 0x2C | Pause/Break | 0x48 | 0 | 0x62 | ||||
P | 0x13 | - | 0x2D | Insert | 0x49 | . | 0x63 | ||||
Q | 0x14 | ^ | 0x2E | Home | 0x4A | ||||||
R | 0x15 | @ | 0x2F | Page Up | 0x4B | ||||||
S | 0x16 | [ | 0x30 | Delete | 0x4C | ||||||
T | 0x17 | End | 0x4D | ||||||||
U | 0x18 | ] | 0x32 | Page Down | 0x4E | ||||||
V | 0x19 | ; | 0x33 | Arrow Right | 0x4F | ||||||
W | 0x1A | : | 0x34 | Arrow Left | 0x50 | ||||||
X | 0x1B | 半角/全角 漢字 |
0x35 | Arrow Down | 0x51 | ||||||
Y | 0x1C | , | 0x36 | Arrow Up | 0x52 | ||||||
Z | 0x1D | . | 0x37 | Num Lock | 0x53 | ||||||
/ | 0x38 | ||||||||||
Caps Lock | 0x39 |
<解説> 以下に、記載してある内容は要点だけです。 詳細はプロジェクトファイルを精読願います
(以下は、Harmony v2.04 をもとに作成しています。最新のバージョンとは異なることがあるかもしれませんので注意してください。)
■ MHC設定
■ Options
■Pin Settings
項目 | ポート設定(その1) | ポート設定(その2) |
MHC | ||
備考 | デフォルトからの変更要領: UARTポート設定 RC2: U6TX RG9: U6RX |
デフォルトからの変更要領: I2Cポート設定 RA2: SCL2 RA3: SCLA |
■ I2Cインターフェースのキャラクタ液晶表示ライブラリの追加要領
キャラクタ液晶表示のライブラリ lcd_ACM1602_lib_i2c.h と lcd_ACM1602_lib_i2c.cを main.cと同じフォルダにコピーして、
プロジェクトに追加します。
(使い方 → I2Cインターフェースキャラクタ液晶表示制御 参照)
プロジェクトへの追加は以下のようにします。
■app.hに、青字部の修正、追加をします。
①APP_STATESの列挙型変数を以下のように変更します。
typedef enum
{
/* Application pixels put*/
APP_STATE_INIT=0,
APP_STATE_OPEN_HOST_LAYER,
APP_STATE_WAIT_FOR_HOST_ENABLE,
APP_STATE_HOST_ENABLE_DONE,
APP_STATE_WAIT_FOR_DEVICE_ATTACH,
APP_STATE_DEVICE_ATTACHED,
APP_STATE_READ_HID,
APP_STATE_DEVICE_DETACHED,
APP_STATE_CHANGE_DEVICE_PARAMETERS,
APP_USART_STATE_DRIVER_OPEN,
APP_USART_STATE_CHECK_FOR_STRING_TO_SEND,
APP_USART_STATE_DRIVER_WRITE,
APP_STATE_ERROR
} APP_STATES;
②構造体APP_DATAのメンバーを以下のように変更します。
typedef struct
{
/* USB Application's current state*/
APP_STATES state;
/* USART Application task state */
APP_STATES usartTaskState;
/* Unique handle to USB HID Host Keyboard driver */
USB_HOST_HID_KEYBOARD_HANDLE handle;
/* Unique handle to USART driver */
DRV_HANDLE usartDriverHandle;
/* Number of bytes written by the USART write*/
uint32_t nBytesWritten;
/* Size of the buffer to be written */
uint32_t stringSize;
/* Buffer used for USART writing */
uint8_t string[64];
/* Holds the current offset in the string buffer */
uint16_t currentOffset;
/* Flag used to determine if data is to be written to USART */
bool stringReady;
/* Flag used to select CAPSLOCK sequence */
bool capsLockPressed;
/* Flag used to select SCROLLLOCK sequence */
bool scrollLockPressed;
/* Flag used to select NUMLOCK sequence */
bool numLockPressed;
/* Holds the output Report*/
uint8_t outputReport;
/* Application current data buffer */
USB_HOST_HID_KEYBOARD_DATA data;
/* Application last data buffer */
APP_DATA_LAST_DATA lastData;
} APP_DATA;
以下、app.h
■app.cに、青字部の修正、追加をします。
① MHCが作成したapp.cを修正するより、マイクロチップのサンプルソフトhid_basic_keyboardのapp.c
( "C:\microchip\harmony\v2_04\apps\usb\host\hid_basic_keyboard")を修正した方が
簡単なので app.cを入れ替えます。
②インクルードファイルを追加します。stdio.hがないと、sprintf( )がコンパイラのバージョンによってコンパイルでエラーが
でることがあります。
#include "stdio.h"
③キャラクタ液晶制御のバッファーを定義します。 またキャラクタ液晶とTeraTermに表示する文字列も定義します。
char Buf[32];
char strUART[16];
char moji_Esc[] = "Esc";
char moji_Tab[] = "Tab";
char moji_Enter[] = "Enter";
char moji_BackSpace[] = "Back Space";
char moji_CapsLock[] = "Caps Lock";
……
……
char moji_F10[] = "F10";
char moji_F11[] = "F11";
char moji_F12[] = "F12";
char moji_10keyEnter[] = "10key Enter";
④NOP()による遅延関数 delay_us( )、delay_ms( )を定義しておきます。
int delay_Clock = 200000000; //200MHz
void delay_us(volatile unsigned int usec) //1μsec遅延
{
volatile int count;
count = (int)(delay_Clock/20000000)*usec;
……
……
⑤ keyValueに係るコメントを追加しただけです。 PICの制御には無関係です。
/* Usage ID to Key map table */
const char *keyValue[] =
{
……
……
}
⑥ USB初期化に際して、APP_Tasks( )から呼び出されます。
void APP_USBHostHIDKeyboardEventHandler(USB_HOST_HID_KEYBOARD_HANDLE
handle,
USB_HOST_HID_KEYBOARD_EVENT event, void * pData)
{
switch ( event)
{
case USB_HOST_HID_KEYBOARD_EVENT_ATTACH:
appData.handle = handle;
appData.state = APP_STATE_DEVICE_ATTACHED;
……
……
}
⑦ 英数字が打鍵された場合、キャラクタ液晶やTeraTermに文字を表示するための補助関数です。
void ys_Char(USB_HID_KEYBOARD_KEYPAD _keyCode) //英数文字キー
{
//I2Cキャラクタ液晶表示
lcd_ACM1602_cmd_i2c(0x80); //1行目の先頭へ
sprintf(Buf,"key=0x%02X ",_keyCode);
lcd_ACM1602_str_i2c(Buf);
lcd_ACM1602_cmd_i2c(0xC0); //2行目の先頭へ
sprintf(Buf,"%c ",appData.string[appData.currentOffset]);
lcd_ACM1602_str_i2c(Buf);
}
⑧ 記号が打鍵された場合、キャラクタ液晶やTeraTermに文字を表示するための補助関数です。
対象の記号キーは keyCodeが 16進表示で0x〇〇と表示できるキーです。
void ys_Char_0xXX(USB_HID_KEYBOARD_KEYPAD _keyCode, char myChar) //一般記号文字キー
{
……
……
}
⑨記号が打鍵された場合、キャラクタ液晶やTeraTermに文字を表示するための補助関数です。
対象の記号キーは keyCodeが 16進表示で0xFFFFFF〇〇と表示できるキーです。 具体的には \ と _ の場合です。
void ys_Char_0xFFFF(USB_HID_KEYBOARD_KEYPAD _keyCode, char myChar) //特別扱い文字キー: \ _
{
……
……
}
⑩エンターキーが打鍵された場合、キャラクタ液晶やTeraTermに文字を表示するための補助関数です。
void ys_Function_Enter(USB_HID_KEYBOARD_KEYPAD _keyCode) //エンターキー
{
……
……
}
⑪一般機能キー(Esc、Tab、ファンクションキーなど)が打鍵された場合、キャラクタ液晶やTeraTermに文字を
表示するための補助関数です。
void ys_Function_0xXX(USB_HID_KEYBOARD_KEYPAD _keyCode, char* str0) //一般機能キー
{
……
……
}
⑫特別扱い機能キー("カタカナ" "変換" "無変換"キー)が打鍵された場合、キャラクタ液晶やTeraTermに文字を
表示するための補助関数です。
void ys_Function_0xFFFF(USB_HID_KEYBOARD_KEYPAD _keyCode, char* str0)
//特別扱い機能キー //"カタカナ" "変換" "無変換"
{
……
……
}
⑬シフトしない場合の 各キー毎の分岐をおこなう関数です。
void ys_NonShift_MapKey(USB_HID_KEYBOARD_KEYPAD keyCode, uint8_t outputReport)
//非シフトモードのキーマップ関数
{
……
……
}
⑭シフトした場合の 各キー毎の分岐を行う関数です。
void ys_Shift_MapKey(USB_HID_KEYBOARD_KEYPAD keyCode, uint8_t outputReport) //シフトモードのキーマップ関数
{
……
……
}
⑮取得したキーコードを最初に分岐させる関数です。
void APP_MapKeyToUsage(USB_HID_KEYBOARD_KEYPAD keyCode) //keyCode: 打鍵キーコード
{
……
……
}
⑯PICが立ち上がったらキャラクタ液晶に"USB device HID" と "Keyboard demo" を表示しています。
void APP_Initialize ( void )
{
……
……
lcd_ACM1602_cmd_i2c(0x80); //1行目の先頭へ
lcd_ACM1602_str_i2c("USB device HID ");
delay_ms(1000);
cd_ACM1602_cmd_i2c(0xC0); //2行目の先頭へ
lcd_ACM1602_str_i2c(" Keyboard demo ");
⑰UARTに 表示データを送信しています。 APP_Tasks( ) 1サイクル毎に最後で呼ばれています。
void APP_USART_Tasks(void)
{
……
……
}
⑱ APP_STATE_INIT は、USB初期化に際し一度だけ呼ばれます。
void APP_Tasks ( void )
{
switch ( appData.state )
{
/* Application's initial state. */
case APP_STATE_INIT:
⑲ USBの初期化が完了して、キーボード用USBコネクタの接続待ちのステートです。 キーボード用のUSBコネクタが
途中で抜かれた場合 このステートでの待ちとなります。
case APP_STATE_HOST_ENABLE_DONE:
⑳ キーボード用のUSBが接続された時に通過するステートです。この後キーボードとの送受信ステートAPP_STATE_READ_HIDに
移行します。
case APP_STATE_DEVICE_ATTACHED:
(21) キーボードとの送受信ステートです。 このステート内で複数回キーボード情報を取得します。 すなわち APP_Tasks( )
1サイクルの中で複数回のキーボード情報が取得されます。
case APP_STATE_READ_HID:
(22)APP_Tasks( ) 1サイクルの最後に APP_USART_Tasks( )が呼ばれ UARTへの送信が行われます。
/* Call the USART task routine */
APP_USART_Tasks(); //UART]側に送信
以下、app.c