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

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

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
WindowsパソコンにUSB接続して使う現行方式はそれなりに便利ではありますが、ときとしてWindows
のしがらみから開放されて、小さいながらも独立した一個のパソコンとして機能したいと思うこともあります。
独立大作戦の作戦その1はCRTインターフェースボードの製作です。
作戦その2はキーボードインターフェースです。
そして作戦その3は、SDカードインターフェースです。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜

[第9回]


●テストプログラムの説明

IN/OUTサブルーチンから先に説明します。
下がサブルーチンSINOUTのアセンブルリストです。
テストプログラム全体のリストは前回にあります。

              ; D:out data E:in data
816E 0608     SINOUT:LD B,08
8170 7A       SINOUT2:LD A,D
8171 2F         CPL
8172 D381       OUT (81),A;data out
8174 3E01       LD A,01
8176 D383       OUT (83),A;pc0=1 out ~I_
8178 7A         LD A,D
8179 17         RLA
817A 57         LD D,A
817B 3E00       LD A,00
817D D383       OUT (83),A;pc0=0 out _I~
817F DB80       IN A,(80)
8181 2F         CPL
8182 1F         RRA
8183 7B         LD A,E
8184 17         RLA
8185 5F         LD E,A;data in
8186 05         DEC B
8187 C27081     JP NZ,SINOUT2
818A 3E01       LD A,01
818C D383       OUT (83),A;pc0=1 out ~I_
818E C9         RET
              ;

最初にDレジスタの内容(8ビット)を82C55のBポートから出力します。
74HC05によって出力が反転しますから、送出する前に値を反転しておきます。
そのときのDレジスタの値を反転した8ビットの値がPB7〜PB0から出力されますが、MOSIのラインには74HC05を介してPB7しかつながっていませんから、結局そのときのDレジスタのビット7の値のみがSDカードに伝えられることになります。
Dレジスタのビット7の値がPB7から出力された直後に、PC0から1を出力します。
出力は74HC05によって反転されますから、SCKのラインがHからLになります。
逆にPC0から0(L)を出力すると、SCKのラインはHになります。
ここでの注意は、CポートからはSCKのほかにCSも出力される(PC1)という点です。
PC0からSCKを出力するときにPC1の出力が変わってしまわないように、PC0のみを出力するようにします(Cポートのビット出力モードを使います)。

通常はこのサブルーチンが呼ばれた時点でSCKラインはLになっていますから、第1回目のパルス出力(アドレス8176)は冗長ですが、プログラムの流れでこのようになります。
ビットデータ送出後にDレジスタの値を1ビット左シフトします。
こうすることでPB7からDレジスタの値がパラレルからシリアルに変換されて出力されることになります。
Z80には各レジスタを直接シフトする命令がありますが、MYCPU80やND8080との互換性を考えて、8080の命令だけでプログラムします。

前回確認しました通りパルス出力周波数はSDカードの規定値よりも低いので、特に待ち時間ループなどを挿入することなく、Dレジスタを左シフトしたらすぐにSCK出力をHにします。
そして直後にSDカードからのデータをPA0から入力します。
74HC05によって入力データも反転しますから、入力したら値を反転します。
入力データはEレジスタに入れますがここでテクニックを使っています。
先にRRAコマンドでAレジスタを右シフトします。
こうするとPA0から入力したデータ(Aレジスタのビット0)がキャリーフラグに入ります。
そのあとでEレジスタを左シフトします。
するとEレジスタがビット7←ビット0の方向に1ビットシフトされて、ビット0にはキャリーフラグの値が入ります。
以上の動作を8回繰り返すと、Dレジスタの値8ビットがシリアル送出され、SDカードからのデータ8ビットがEレジスタに読み込まれます。
最後にSCK出力をLにします。
このようにSPI通信を82C55を使って行なう場合、このSINOUTサブルーチンが肝心要(かなめ)の部分で、これさえ出来れば、あとはフロー通りにプログラムするだけです。

肝心要のSINOUTサブルーチンの説明が済みましたので、次にメインプログラムの説明に入ります。
[第7回]にフローチャートがありますから、適宜参照してください。

8100 3E90     START0:LD A,90
8102 D383       OUT (83),A
              ;card init
8104 2E0A       LD L,0A
8106 CD6E81   START01:CALL SINOUT
8109 2D         DEC L
810A C20681     JP NZ,START01

最初に82C55の向きを設定します。
Aポートが入力でBポート、Cポートを出力に設定します。
コントロールワード90Hをアドレス83Hに出力します。
出力に設定したポートは全ビットが0になります。
74HC05によってラインの出力は反転しますから、82C55の向きを設定すると、ラインの出力はHになります。
CSラインをHにしたままでSCKパルスを74回以上送ります。
1回のSINOUTサブルーチンコールで8パルスが出力されますから、サブルーチンを10回(0AH)コールして、80パルス出力します。
ここでうっかりしてDレジスタをHにするのを忘れていました。
このときMOSIラインからはDレジスタの値(何が入っているかは不明)が出力されてしまいます。
幸いCSがHの状態なので、このまま実行しても特に支障はありませんでした。

次はCMD0の送出です。

              ;CMD0 out
810D 3E02       LD A,02
810F D382       OUT (82),A;CS=L
8111 1640       LD D,40
8113 CD6E81     CALL SINOUT
8116 0604       LD B,04
8118 C5       START02:PUSH BC
8119 1600       LD D,00
811B CD6E81     CALL SINOUT
811E C1         POP BC
811F 05         DEC B
8120 C21881     JP NZ,START02
8123 1695       LD D,95
8125 CD6E81     CALL SINOUT
8128 16FF     START03:LD D,FF
812A CD6E81     CALL SINOUT
812D 63         LD H,E
812E 7B         LD A,E
812F F5         PUSH AF
8130 CD4B10     CALL HXDP2
8133 F1         POP AF
8134 FE01       CP 01
8136 C22881     JP NZ,START03
              ;

ここからはCSをLにします。
74HC05によってラインの出力は反転しますから、PC1を1にします。
DレジスタにCMD0(40 00 00 00 00 95)をセットしてSINOUTサブルーチンをコールします。
送出したらFFを出力しながらレスポンスを待ちます。
その状態をモニタするために8ビット受信するごとに16進数2桁で画面表示します。
HXDP2はHレジスタの値を16進数2桁で表示するZB3BASICのシステムサブルーチンです。
レスポンス01が来たら次の処理(CMD1の送出)に移ります。

CMD1の送出です。

              ;CMD1 out
8139 1641     START07:LD D,41
813B CD6E81     CALL SINOUT
813E 0604       LD B,04
8140 C5       START08:PUSH BC
8141 1600       LD D,00
8143 CD6E81     CALL SINOUT
8146 C1         POP BC
8147 05         DEC B
8148 C24081     JP NZ,START08
814B 16FF       LD D,FF
814D CD6E81     CALL SINOUT
8150 16FF     START09:LD D,FF
8152 CD6E81     CALL SINOUT
8155 63         LD H,E
8156 7B         LD A,E
8157 F5         PUSH AF
8158 CD4B10     CALL HXDP2
815B F1         POP AF
815C B7         OR A;00?
815D CA6881     JP Z,END
8160 FE01       CP 01
8162 C25081     JP NZ,START09
8165 C33981     JP START07
8168 CD1B10   END:CALL CRLF
816B C33310     JP REENT
              ;

DレジスタにCMD1(41 00 00 00 00 FF)をセットしてSINOUTサブルーチンをコールします。
送出したらFFを出力しながらレスポンスを待ちます。
その状態をモニタするために8ビット受信するごとに16進数2桁で画面表示します。
レスポンス00が来たら処理を終ります(END:にジャンプします)。
00、01以外ならSTART09:に戻ってレスポンスを待ち続けます。
01ならSTART07:に戻ってCMD1を送出して、以後の処理を繰り返します。
END:では表示を改行するため、CRLFをコールしたあと、システムに戻ります。
CRLFは画面表示を改行するZB3BASICのシステムサブルーチンです。
REENTはZB3BASICシステムに戻るエントリポイントです。

●テストプログラムの実行

テストプログラムsdcdif2k.binをND80Z3.5で実行しました。

logfile nd80zlog\11031038.txt open

ND80ZVに接続しました
0001 0000 - z
1000 00C3 - 
*** nd80z3 basic ****
ndwr2h.bin loaded,from E23F to E535
>/ld sdcdif2k.bin,8100
loading SDCDIF2K.BIN ...008f(143)bytes loaded,from 8100 to 818E
>jp 8100
FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01
FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01FF01
FF01FF01FF00
>jp 8100
FF01FF01FF00
>/exit
0000 00C3 - 
リモート接続を終了しました
logfile closed at Thu Nov 03 10:41:20 2016  

このテストプログラムはCMD0とCMD1をSDカードに送って初期化を実行するだけのプログラムです。
CMD0、CMD1を送ってレスポンスを確認するだけです。
カードの読み出しなどはしていません。

プログラムを2回実行しています。
1回目は電源投入直後なので、CMD1で00が来るまでに少し時間がかかっています。
FF01が連続しています。
先頭のFF01はCMD0のレスポンスです。
次からのFF01はCMD1のレスポンスです。
2回目のプログラム実行ではすぐに00が来ました。

どうやらここまではうまくいったようです。

SDカードインターフェースの製作[第9回]
2016.11.4upload

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