マイコン独立大作戦
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
前へ
次へ
ホームページトップへ戻る