2016.10.25
前へ
次へ
ホームページトップへ戻る

マイコン独立大作戦
キーボードインターフェースの製作

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
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

前へ
次へ
ホームページトップへ戻る