マイコン独立大作戦
キーボードインターフェースの製作
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
WindowsパソコンにUSB接続して使う現行方式はそれなりに便利ではありますが、ときとしてWindows
のしがらみから開放されて、小さいながらも独立した一個のパソコンとして機能したいと思うこともあります。
独立大作戦の作戦その1はCRTインターフェースボードの製作です。
そして作戦その2は、やっぱりキーボードインターフェースしかありませんでしょう。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
[第15回]
●ND80Z3.5のキー入力プログラム(3)
前回の奇妙な現象なのですが、なかなかその原因がわからず腕を組んで考え込んでしまいました。
どうも考え疲れてしばらく眠り込んでいたようでありますが。
やっぱり脳細胞にも休養が必要です。
ふと気が付いて、もう一度よくよく考えてみましたら。
異常が発生したところは、どうやらビット0が本来1のはずなのに、それが0になってしまうらしい、ということに気が付きました。
はて面妖な…。
おお。
ひょっとして…!
そういうことだったのか!
やっと原因がわかりました。
原因はPIC16F87がCLK入力で割込みを使うために、RB0をINT端子として使ったことにありました。
いえ。
割込みそのものが原因ではありません。
割込みを使うために、本当は8ビットにパラレル変換したデータをRB7〜RB0に出力したいところを、それができませんからRB0の代わりにRA0を使わざるを得なかったところに原因がありました。
PIC16F87のプログラムは[第12回]でお見せしました。
そのdataoutの部分です。
dataout
movwf outdata
movwf PORTB
btfsc outdata,0
goto set0
bcf PORTA,0
goto next
set0
bsf PORTA,0
next
clrf dataokmk
return
|
このサブルーチンがCALLされる時点で、シリアルからパラレルに変換した8ビットのスキャンコードはwレジスタにあります。
それをワークレジスタoutdataに保存したあと、PORTBから出力しますが、RB0は割込みのためINT端子として入力に設定しているために使えません。
そこでそのあとoutdataのビット0を調べて、それが0のときはRA0から0を、1のときはRA0から1を出力します。
POATBから上位7ビットが出力されてから、RA0に1がセットされて出力されるまではほんの短い時間です。
PIC16F87は内部発振クロック8MHzで動作していますから、1命令クロックはその1/4の2MHzです。
btfsc outdata,0 この場合は1クロック
goto set0 2クロック
:
:
set0
bsf PORTA,0 1クロック
合計4クロックですから、0.5×4=2μsです。
余談ですけれど、こういう場合、Cコンパイラではお手上げでありましょう。
こういうところはコンパイラがアセンブラには逆立ちしたって勝てない、コンパイラが全く無力になってしまうところです。
でも、IO制御では実行時間を正確に知らなければいけない場合が意外と多いのですよ。
アセンブラを使いましょう!
さて。
本題に戻って、その実行クロックなのですが。
このたった2μsの間に図のようなことがおきていたと考えられます。
この可能性に気が付かなかったのはまことにうかつでありました。

ここでRA0がL→Hのときの図になっているのには理由があります。
一般的なキー操作では、あるキーが離れてから別のキーが押されるという流れになります。
前に押されていたキーが離れたとき、PIC16F87からの8ビットデータ出力は00になります。
その後、次のキーが押されたときにそのキーコードのビット0が1だったとすると、上図のようになります。
そのときにCPU側のプログラムでIN A,(81)が図のタイミングで実行されると、本来はビット0が1であるのにもかかわらず、0が読み込まれてしまいます。
原因が分かりましたから、そのような誤読込みを避けるために、CPU側のキー入力プログラムを少し直しました。
2016/10/22 22:11 keypic1e.txt
END=817D
;;; keyboard test program from pic16f87
;16.10.8 10.20
;
ORG $8100
;
ADISP=$1015
HXDP2=$104B
;
8100 C30481 JP START0
8103 00 SHFTMK:DB 00
8104 3E8A START0:LD A,8A
8106 D383 OUT (83),A
8108 3EFF LD A,FF
810A D382 OUT (82),A
810C 0600 START1:LD B,00
810E DB81 START2:IN A,(81);keycode
8110 B7 OR A
8111 CA0C81 JP Z,START1
8114 4F LD C,A
8115 DB81 IN A,(81)
8117 B9 CP C
8118 C20E81 JP NZ,START2
811B CD5681 CALL HEXDP
811E 79 LD A,C
811F FE1A CP 1A;=Z
8121 C8 RET Z
8122 B8 CP B
8123 CA4281 JP Z,SHFTCK;already disp,but shift?
8126 41 LD B,C
8127 DB82 IN A,(82);shift check
8129 320381 LD (SHFTMK),A
812C B7 OR A
812D FA3981 JP M,SHFTIN
8130 110092 NOSHFT:LD DE,$9200
8133 CD6581 ASCDP:CALL ASCDPS
8136 C30E81 JP START2
8139 320381 SHFTIN:LD (SHFTMK),A
813C 110093 LD DE,$9300
813F C33381 JP ASCDP
;
8142 DB82 SHFTCK:IN A,(82)
8144 B7 OR A
8145 FA0E81 JP M,START2
8148 3A0381 LD A,(SHFTMK)
814B B7 OR A
814C F20E81 JP P,START2
814F AF XOR A
8150 320381 LD (SHFTMK),A
8153 C33081 JP NOSHFT
;
8156 3E5B HEXDP:LD A,5B;[
8158 CD1510 CALL ADISP
815B 61 LD H,C
815C CD4B10 CALL HXDP2
815F 3E5D LD A,5D;]
8161 CD1510 CALL ADISP
8164 C9 RET
;
8165 210091 ASCDPS:LD HL,$9100
8168 C5 PUSH BC
8169 79 LD A,C
816A 0630 LD B,30
816C BE ASCDPS2:CP (HL)
816D CA7781 JP Z,ASCDPS3
8170 23 INC HL
8171 05 DEC B
8172 C26C81 JP NZ,ASCDPS2
8175 C1 POP BC
8176 C9 RET
8177 62 ASCDPS3:LD H,D
8178 7E LD A,(HL)
8179 CD1510 CALL ADISP
817C C1 POP BC
817D C9 RET
;
;END
ADISP =1015 ASCDP =8133 ASCDPS =8165
ASCDPS2 =816C ASCDPS3 =8177 HEXDP =8156
HXDP2 =104B NOSHFT =8130 SHFTCK =8142
SHFTIN =8139 SHFTMK =8103 START0 =8104
START1 =810C START2 =810E
|
もとはIN A,(81)を1回だけ実行していたところを、2回実行して、もし2回の結果が不一致だったら、もう一度読み直すように変更しました。
START2:IN A,(81)
が実行されてから、次のIN A,(81)が実行されるまでには、以下の命令が実行されます。
OR A 4クロック
JP Z,START1 10クロック
LD C,A 4クロック
IN A,(81) 11クロック
合計29クロックです。
ND80Z3.5のCPUクロックは6MHzですから、上の命令の実行時間は29/6=4.83μsです。
つまりここで2度読みすることで2μsのギャップは確実に避けることができます。
この計算からは、2度読みして結果が不一致ならば後で読んだ値を正しい値として採用すればよいということになりますが、まあ、どちらにしてもわずかな時間ですから、このようなプログラムにしておけばよいでしょう。
下が実行結果です。
logfile nd80zlog\10231453.txt open ND80ZVに接続しました 0001 0000 - z 1000 00C3 - *** nd80z3 basic **** ndwr2h.bin loaded,from E23F to E535 >/ld keypic1e.bin,8100 loading KEYPIC1E.BIN ...007e(126)bytes loaded,from 8100 to 817D >usr($8100) [FF][FF][1C]A[1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C ][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C ][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C ][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C ][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C ][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C ][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C ][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C ][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C ][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C ][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C ][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C ][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C ][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C ][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C][1C ][32]B[32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][3 2][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][3 2][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][3 2][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][3 2][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][3 2][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][3 2][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][3 2][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][3 2][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][3 2][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][32][3 2][32][32][32][32][32][32][32][32][32][32][32][21]C[21][21][21][21][21][21][21][ 21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][ 21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][ 21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][ 21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][ 21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][ 21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][ 21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][ 21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][ 21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][ 21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][ 21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][ 21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][ 21][21][21][21][21][21][23]d[23][23][23][23][23][23][23][23][23][23][23][23][23] [23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23] [23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23] [23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23] [23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23] [23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23] [23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23] [23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23] [23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23] [23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23] [23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23] [23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23] [23][23][23][23][23][23][23][23][23][23][23][23][23][23][21]C[21][21][21][21][21 ][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21 ][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21 ][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21 ][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21 ][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21 ][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21 ][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21 ][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21 ][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21 ][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21 ][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][21][23 ]d[23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][2 3][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][2 3][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][2 3][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][2 3][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][2 3][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][2 3][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][2 3][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][2 3][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][2 3][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][2 3][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][2 3][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][23][2 3][1A] > |
どうやらこれでおかしなところはなくなったようです。
そこで最後の仕上げです。
16進数の表示はデバッグのためには役立ちますが、実際のキー入力プログラムでは不要です。
というかはっきり言ってじゃまです。
そこでプログラムを変更して16進数の表示部分をなくすればよいのですが、今はまだテストプログラムの段階ですから、ちょいとウラ技を使って、次のようにしました。
>cm 811b 811B CD-00 811C 56-00 811D 81-00 811E 79- >usr($8100) 1234567890abcdeABCDE!"#$%xy >/exit 0000 00C3 - リモート接続を終了しました logfile closed at Sun Oct 23 14:56:47 2016 |
なにをやったかといいますと、メモリーにロードされているマシン語プログラムの16進数表示ルーチンのコール命令CD5681をCMコマンドで00(NOP)に書き換えてしまったのです。
そのようにしておいてから、USR($8100)を実行すると、16進数の表示が行なわれなくなって、ご覧のような結果が得られました。
これまたコンパイラなどでは、したくてもできない芸当です。
いやあアセンブラ(&マシン語)って、ほんとに便利です!
それはともかくとしまして、ND80Z3.5が優れものであることがご理解いただけましたでしょうか(ND80ZV、ND8080も同じです)。
キーボードインターフェースの製作[第15回]
2016.10.25upload
前へ
次へ
ホームページトップへ戻る