PS2キーボードを接続してみます

〔PICの動かせ方入門に戻る〕


USBキーボードが有りますが、これはマイコンがUSBのホスト機能(OTG)が無いと接続できません。
少し前までミニDIN6Pコネクターで接続するPS2キーボードが有りました、これはキーが押されると
ON/OFFのシリアルパルスパターンを送って来ますのでこれをデジタル端子に接続して読み取れば
押されたキーコードが判別します。
ですのでこのPS2キーボードをPIC(16F1938)に接続して見たいと思います。
(プログラムをコンパイルした所、約4KWord程だったのでそれ以上のPICをお使いください)

ミニDIN6Pコネクター図  左図はミニDIN6Pコネクター(オス:キーボード側)のピン構成図です、
 なのでパソコン側(メス)からだと番号が反転します、注意しましょう。

 出来るならマルツのこちらこちら、メス側コネクタを使った方が良いです
 私は注文が面倒だったのでコネクタ部分を切断してヘッダピンを半田付け
 しました。
 尚、図の線の色はMyキーボードでの色なので他は異なるかもです。

 電源(VCC)は5Vです、キーボードの裏に100mA(物により異なる)、結構電気食いかもね。
 PICには、5:CLK/1:DATAをデジタル入力ピンに接続します、CLK/DATAの端子には
 プルアップ抵抗(1-10KΩ)が必要です。

キーボードからの送信データフォーマット

1データは11ビットでの構成です。(DATAライン)
送信データのフォーマット

機能 ビット数 内容
スタート ビット 通常はHIGHで、ビットLOWで開始
データ ビット スキャン コードで1byteです、LSBから送信される
"0"キーなら0x45だから”10100010”の順番で送信
パリティ ビット 奇数パリ ティです
データビットのHIGHが奇数なら"0"となり、
偶数なら"1"として常に奇数とする。
ストップ ビット ビットは HIGHで終了

送信データの波形
[0(ゼロ)]キーを押した時の波形です、CLKが赤(上)でDATAが黄色(下)です。
CLKの立下りでデータを読みます、"0 10100010 0 1"となる

"0"のASCII(キャラクタ)コードは0x30ですが、キーボードはスキャンコード0x45で送ってきます。
ですので変換が必要と言う事になります。

"0"を押した時に"0x45"が発生しますが、離した時は"0xF0"と"0x45"が発生します。
又、"↑"を押した時に"0xE0","0x75"が発生し、離した時は"0xE0","0xF0","0x45"が発生、
と言う感じに"0xE0"が付く拡張キーが有ったりします。
詳しくは、こちらのスキャンコード一覧表を参照下さい。

こちらに日本語訳版の"PS/2 マウス/キーボード プロトコルとインターフェース"が有ります。
  因みに、PS2英語仕様書サイトは こちらに有ります。
※ キーボードの状態や設定情報に、"NumLock"等のLED点灯要求データをキーボードに送信可能
  ですが、ここでは行っていません、送信コマンドに対する内容はこちらを参考にして下さい。
※ キーボードに電源が入った時に、"0xAA(Basic Assurance Test)"コマンドが送信されます。

《 配線について 》

実態配線図

キーボードのCLKライン(黄)をPICの21(RB0)番ピンに接続、DATAライン(白)を22(RB1)番ピンに接続
しています。
CLKの波形がLOWになると状態変化割り込みを掛けてDATAラインを読みに行っています、
ですのでCLKラインは割り込みが掛けられるピンにする必要が有ります。
また、プルアップ抵抗はPIC内蔵を使っています。尚、PICは右上が1番ピンです。

キーデータの表示用としてI2C接続のLCDを使っていますが詳細はこちらを参考にして下さい。

《 ダウンロードプログラムについて 》

PS2キーボードのライブラリなのですが、実はこちらの"Arduino Playground"に有る記事の内容を
利用し、ダウンロードはこちの最新バージョン2.4(2015/05/10現在)を使っています。
ですが、日本語キーボード対応でなかったので対応版に改造してPIC用に移植しています。
(GNU Software なので改造・配布は大丈夫だと思いますのでぇ....)

改造点は
・ 日本語101キーボード用に追加、又、カナキーも入力可能
・ メモリを節約する為に、"German and French keyboard"のデータを削除
  (因みに、英語キーボードのデータも削除すれば4KWord以内でも収まりますがぁ....)
・ [F1]-[F4]キーを入力可能にして、キーコードデータを一部変更

↓ここからサンプルプログラムソースファイルをダウンロードして下さい。
PS2Keyboard.lzh(Version 2.4.sk001)

プログラムソースをダウンロードしたら、MPLAB Xにてプロジェクトを作成します。
以下のファイルをプロジェクトディレクトリにコピーしてプロジェクトに取込んで下さい。
次にコンパイルPIC書き込みを実行して下さい。
MPLAB(R) XC8 C Compiler Version 1.32コンパイラを使用しています。

ダウンロードファイルを解凍すると下記の様なファイル構成です。
 PS2KB.c・・・・・・・・・・・ 本体のサンプルプログラムソースファイル(日本語キーボードテスト用)
 skPS2Keyboard.c・・・ PS2キーボード用関数ライブラリソース(Version 2.4の改造移植版)
 skPS2Keyboard.h・・・ ヘッダファイル(Version 2.4の改造移植版)
 skS1.c・・・・・・・・・・・・・ PIC用S1標準関数ライブラリ
 skS1.h・・・・・・・・・・・・・ PIC用S1標準関数ヘッダファイル
 // 以下はI2C接続LCD表示用
 skI2CLCDlib.c・・・・・・ I2C接続LCDライブラリ関数ソースファイル
 skI2CLCDlib.h・・・・・・ I2C接続LCDライブラリ用インクルードファイル
 skI2Clib.c・・・・・・・・・・ I2C通信を行う関数ソースファイル
 skI2Clib.h・・・・・・・・・・ I2C通信を行う関数のインクルードファイル

 尚、CPUのクロックは8MHzを想定しています。
 なので通信速度等(I2C)はシステムクロック8MHzで計算されています。


PS2KB.c

動作結果図  左図がキー入力テスト画面の例です。(カナを入力している所)
 "START KB TEST"が表示されたらキー入力出来ます。
 キーデータは2行目に表示されます。

 [Enter]キーを入力すれば、2行目は消去され先頭から表示開始
 [Shift]キーを押しながらは大文字入力です。

 [ALT]+[カナ/かな]キーON/OFF入力でカナ文字入力切替、
 ONで画面は右上のアイコンが点灯してカナ文字入力可能です、
 OFFでアイコンは消灯し、通常入力モードです。

skPS2Keyboard.h

PS2キーボード用関数のインクルードファイルです。
"skPS2Keyboard.c"を利用する場合に
#include "skPS2Keyboard.h" をプログラムの先頭で記述して下さい。
#define PS2_CLK_PIN      RB0  // PS2キーボードのCLKピンを接続しているポート番号
#define PS2_DATA_PIN     RB1  // PS2キーボードのDATAピンを接続しているポート番号
と記述しています、接続するピンを替える場合は書き換えて下さい。
それと、"ANSELx/TRISx"レジスタで接続するピンはデジタル入力と設定して下さい。
また、接続するピンを内蔵プルアップする場合は"OPTION_REG/WPUB"レジスタにて設定します。
今回は、"PS2KB.c"で下記の様に記述しています。
     OPTION_REG = 0b00000000 ;// デジタルI/Oに内部プルアップ抵抗を使用する
     ANSELB = 0b00000000 ;    // AN8-AN13は使用しない全てデジタルI/Oとする
     TRISB  = 0b00000011 ;    // RB0/1は入力ピン、他は全て出力に割当てる
     WPUB   = 0b00000011 ;    // RB0/RB1は内部プルアップ抵抗を指定する
拡張キーを入力したい場合はこのファイルに変換コードを記述します。

skPS2Keyboar.c

このライブラリは、PS2キーボードからキーデータを読み取る為の関数集です。
キーマップのデータは、日本語と英語キーボードのみ記述してあります。
[F1]-[F4]のファンクションキーのみキーコードが記述してあります。
101キーのテンキー部は数字(NumLockON状態)で入力となっています。

尚、このライブラリは、"skS1.h"と"skS1.c"に記述している状態変化割り込み関数 と一緒に使う必要が有ります。

PS2キーボード用関数の使い方を説明します。

PS2KB_Init(type)
 PS2キーボードの初期値設定を行う処理です。
  type:使用するキーボードのタイプを指定(PS2_KBTYPE_JP=日本語 PS2_KBTYPE_US=英語)
 例)
 PS2KB_Init(PS2_KBTYPE_JP) ;
ans = PS2KB_available( )
 キーバッファにキーデータが有るかチェックを行う処理です。
  ans :戻り値、1=キーコードが有る 0=キーコードは無し

ans = PS2KB_read( )
 キーバッファからキーデータを取り出す処理です。
  ans :1byteのキャラクタコードを返します、−1ならエラーです。
 例)
 int c ;

 if (PS2KB_available()) {
      c = PS2KB_read() ;
       if (c > 0) {
            LCD_Putc(dt) ;
       }
 }
PS2KB_interrupt( )
 キーボードが押された時にキーコードを読み取る為の割り込み処理です。
 この関数はメインプログラムの割込み関数で呼びます。(下記のIO状態変化の割込み関数を参照)

skS1.h/skS1.c

このライブラリは、標準的に利用するだろうと思われる関数を集めた物です。
この中にピンの状態変化割込みを行う為の関数集が有ります、この部分のみを説明して置きます。

今回はRB0ポートを状態変化ピンに使っているので、"PS2KB.c"で下記の様に記述しています。
#define PS2KB_IOC_RB0    0x01 // PS2キーボードの状態変化割込みのポート(RB0)のビット位置情報

     // RB0の状態が立下がったら割込みを発生させる為の初期化処理
     IOC_Init(PS2KB_IOC_RB0,IOC_FALLING) ;
異なるピンを使う場合は変更する必要が有りますが、割込みを行うピンはポートやレジスタ名が
PIC(12F/16FはOKと思われる)により異なるので注意が必要です、データシートを見ましょう。

IO状態変化の割り込み関数の使い方を説明します。

IOC_Init(portno,edge)
 IO状態変化の割り込みが出来る様に初期化する処理です。
  portno:割り込みを行うポート(RB0/RA0)のビット位置情報
  edge :割り込みを行う場合の波形の状態を指定
       IOC_RISING(立上がり) IOC_FALLING(立上がり) IOC_CHANGE(両方)
 例)
 IOC_Init(0x01,IOC_RISING) ;  // RB0(RA0)の立ち上がりで割り込み
 IOC_Init(0x04,IOC_FALLING) ; // RB2(RA2)の立ち下がりで割り込み
ans = InterIOC
 IO状態変化関連の割り込み処理です。
 この関数はメインプログラムの割込み関数で必ず呼びます。
  ans:状態が変化したビット情報(IOCAF/IOCBF)を返します
例)

#define PS2KB_IOC_RB0    0x01 // PS2キーボードの状態変化割込みのポート(RB0)のビット位置情報
#define ETC_IOC_RB2      0x04 // その他の状態変化割込みのポート(RB2)のビット位置情報

void interrupt InterFunction( void )
{
     int ans ;

     // IO状態変化の割り込み処理
     ans = InterIOC() ;
     if (ans != 0) {
          if ((ans & PS2KB_IOC_RB0) == PS2KB_IOC_RB0) {
               // PS2キーボードの割り込み処理
               PS2KB_interrupt() ;
          }
          if ((ans & ETC_IOC_RB2) == ETC_IOC_RB2) {
               // その他RB2の割り込み処理
               ETC_interrupt() ;
          }
     }
}
skI2CLCDlib.c
skI2CLCDlib.h
skI2Clib.c
skI2Clib.h

この内容は”秋月電子I2C接続小型LCDモジュールに表示を行う”を参照下さい。

尚、システムクロックを変えた人は"skI2Clib.c"ファイル内の"InitI2C_Master( )"関数と、
"skI2CLCD.h"のファイルを変更する必要が有ります。
また、I2C通信速度は400KHzで行っています。

《その他》

実験風景
実験中の写真です。

キーボードにデータを送信してキーボードのLED点灯を行う事は、
デジタルピン2本追加と外付け部品が必要なあんばいなので今回見送りました。

PS2テンキー辺りを購入してマイコンの入力デバイスとすれば良さげぇ。
なんてたって2本線のみでスイッチがいっぱい接続ですよぉ。
(ただぁ、スイッチの様に入力させるにはプログラムを作らないとダメですがぁ...)




【きむ茶工房ガレージハウス】
Copyright (C) 2006-2020 Shigehiro Kimura All Rights Reserved.