CH552G 作為一款便宜好用的 USB HID 模擬晶片,我當然是想辦法讓他做到各種神奇功能的東西。而其中一個我很有興趣做的就是能直接輸出中文的鍵盤。
可是這樣問題又來了。到底要怎樣才能讓 CH552G 直接輸出中文呢?作為只有 8bit 的 E8051 處理器,根本沒辦法輸出中文不是嗎?
黑魔法:ALT + BIG5 碼
如果有一定年紀的 Windows 使用者,有玩過一些很早期的網絡遊戲的話應該都知道,早期的中文輸入法對各種遊戲和應用程式的支援很差,有時候即使是輸入法能抓到被遊戲 handle 的鍵盤輸入,也不一定能夠輸出字元到遊戲內的輸入框。這個時候就出現了一個神奇的輸入方法,就是在鍵盤上長按 ALT 然後在 keypad 上輸入該中文字對應的 big-5 碼,之後放開 ALT,中文字就出來了!?

當然,在 Windows 10 之後,有不少應用程式(例如 wordpad)都開始轉用萬國碼 UTF-8,但是只要能夠背下兩邊的碼表的話理論上就能夠不透過任何中文輸入法輸入中文了喔?
那麼,我們讓 CH552G 代替我們按鍵盤不就行了嗎?
理論上是這樣沒錯,但是這裡又有一個問題了,就是
Keyboard_press 沒辦法按數字鍵盤啊???
假設我們要輸入 「你」 好了。它對應的 big-5 和 utf-8 碼分別為 20320 ( 4F60 HEX) 跟 42817 ( A741 HEX),可是當你想著:這很簡單啊,只要
Keyboard_press(KEY_LEFT_CTRL);
Keyboard_write("2");
Keyboard_write("0");
Keyboard_write("3");
Keyboard_write("2");
Keyboard_write("0");
Keyboard_release(KEY_LEFT_CTRL);
的時候,它卻輸出了 “20320” 到電腦上。
嗯?為甚麼會這樣?
原來是因為在 USB HID Keyboard 的定義裡面,數字鍵盤的數字跟你英文字上面那排的 hex code 是不一樣的原因。這個時候為了要轉換這堆數字,我寫了這樣的一個轉換 function,把數字的 char 轉換成 keypad 的 hex code (為了找這個我快花了 3 個晚上,累死)
char PressNumericAsKeypad(char in){
int delayTime = 1;
switch (in) {
case '0':
Keyboard_press('\352');
delay(delayTime);
Keyboard_release('\352');
break;
case '1':
Keyboard_press('\341');
delay(delayTime);
Keyboard_release('\341');
break;
case '2':
Keyboard_press('\342');
delay(delayTime);
Keyboard_release('\342');
break;
case '3':
Keyboard_press('\343');
delay(delayTime);
Keyboard_release('\343');
break;
case '4':
Keyboard_press('\344');
delay(delayTime);
Keyboard_release('\344');
break;
case '5':
Keyboard_press('\345');
delay(delayTime);
Keyboard_release('\345');
break;
case '6':
Keyboard_press('\346');
delay(delayTime);
Keyboard_release('\346');
break;
case '7':
Keyboard_press('\347');
delay(delayTime);
Keyboard_release('\347');
break;
case '8':
Keyboard_press('\350');
delay(delayTime);
Keyboard_release('\350');
break;
case '9':
Keyboard_press('\351');
delay(delayTime);
Keyboard_release('\351');
break;
default:
return in;
break;
}
}
這樣我們就順利的把數字 char 換成 keypad 輸出的 hex code 了。之後就是再寫一個 wrapper function 把整個輸入中文字的流程更容易開發:
//Pass in the Chinese keycode for entering.
//Must be >= 10 (2 digits)
void typeChinese(char* keycode){
//Hold ALT
Keyboard_press(KEY_LEFT_ALT);
delay(20);
for (int i = 0; i < strlen(keycode); i++) {
PressNumericAsKeypad(keycode[i]);
}
//Release ALT
delay(20);
Keyboard_release(KEY_LEFT_ALT);
}
用法:
typeChinese("29509"); //獅
typeChinese("23376"); //子
typeChinese("23665"); //山
typeChinese("19979"); //下
typeChinese("39636"); //體
typeChinese("29694"); //現
typeChinese("39321"); //香
typeChinese("28207"); //港
typeChinese("31934"); //精
typeChinese("31070"); //神
喔喔它動了!?
就是這樣,我們就可以用它來做各種需要輸入中文的神奇蹦蹦裝置了啦~
注:要使用這裡的 code 記得按照 CC BY-SA 的方式注明出處