標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第501回]
●8ビットパラレルデータ伝送(TK80モニタプログラム)
前回はPIC18F2550とZ80CPUとの間での8ビットパラレルデータ伝送について説明をいたしました。
というか、過去記事へのリンクで逃げてしまいました。
今回はその部分のプログラムをお見せすることにいたします。
まずは、Z80版TK80ボード(ND80ZH)の「TK80」モニタプログラムです。
オリジナルのTK80モニタプログラムでは、ここのところは、カセットテープレコーダインターフェイスになっていました。
もちろんいまどきカセットテープではお話しになりませんから、Z80版TK80ボード(ND80ZH)ではそれをPIC16F88を使ってRS232Cインターフェイスにしています。
今回はそこのところを、さらに変更してPIC16F88の代わりにPIC18F2550を使って、RS232Cだけではなくて、USB(HID)での送受信機能が使えるようにしました。
USB(HID)を使うと言っても、実際にその通信部分は全てPIC18F2550がやってくれますから、Z80版TK80ボード(今回の試作ボード)のモニタプログラムは、PIC18F2550との間で、8本のデータラインと4本の制御線を使ってデータをパラレルに送受信すればよく、その方法はPIC16F88でもPIC18F2550でも全く同じです。
そのデータのやり取りの部分をまずZ80版TK80ボード(試作版)の側のプログラムで見てみます。
プログラムサブルーチンの名前はSERIALになっていますが、シリアル送受信を行うのはPIC18F2550ですから、ここのところのPIC18F2550との間でのデータのやり取りはシリアルではなくてパラレルです。
; ;SERIAL OUTPUT ROUTINE ; 027C 4F SOUT:MOV C,A 027D DB98 SOUT2:IN 98 027F E602 ANI 02 0281 CA7D02 JZ SOUT2 0284 79 MOV A,C 0285 D394 OUT 94 0287 3EF9 MVI A,F9; I/Oaddress 94 "out" & STROBE ON 0289 D398 OUT 98 028B DB98 SOUT3:IN 98 028D E602 ANI 02 028F C28B02 JNZ SOUT3 0292 3EFB MVI A,FB; I/Oaddress 94 "out" & STROBE OFF 0294 D398 OUT 98 0296 C9 RET ; ;SERIAL INPUT ROUTINE ; ORG $02A0 ; 02A0 DB98 SIN:IN 98 02A2 0F RRC 02A3 DAA002 JC SIN 02A6 3EFE MVI A,FE;BUSY 02A8 D398 OUT 98 02AA DB94 IN 94 02AC 4F MOV C,A 02AD 3EFF MVI A,FF;READY 02AF D398 OUT 98 02B1 79 MOV A,C 02B2 C9 RET ;
8ビットのデータは8本のデータ線を使って一度に送信、または受信されます。
Z80版TK80ボード(試作版)は、8ビットのデータをI/Oアドレス94にOUT(PICに送信)、またはI/Oアドレス94からIN(PICから受信)します。
このとき送信、受信のそれぞれに、2組のSTROBE信号とREADY/BUSY信号を使います。
Z80CPUからPICへ送信する場合には、Z80側がSTROBE信号を出力します。これはI/Oアドレス98のビット1を0にすることで行われます。
実はZ80版TK80ボード(試作版)がデータをPICに出力するときは、このSTROBEとは別にもう1本、I/Oアドレス98のビット2も0にしなければなりません。
I/Oアドレス98のビット2は、データ出力用レジスタ74HC373(IC4)をアクティブにする信号として使われています([第496回]PIC18F2550回路図)。
PIC18F2550が受信可のときは(通常はこの状態です)、I/Oアドレス98のビット1入力がH(1)になります。
STROBEと同じI/Oアドレスですが、STROBEはOUTで、こちらはINです。回路は別になっていますから、信号がぶつかることはありません。
このラインが1(READY)の時にI/Oアドレス98にデータをOUTしてから、STROBEをL(0)にします。
PIC18F2550は、STROBEラインを監視していて、このラインがLになると、データを読み込んで、処理をする間、READY線をL(0)にします。BUSYです。
Z80CPU側は、PIC18F2550がBUSYを送ってきたことを確認してからSTROBEをOFFにします。
PIC18F2550はデータを読み込んだあと、STROBE信号がOFFになったのを確認してからREADY出力にします。
以上はZ80CPUからPIC18F2550へデータを送る(OUTPUT)プログラムの説明ですが、逆にPIC18F2550からZ80CPUにデータが送られてくるとき(INPUT)も、考え方は全く同じです。
データの読み込みもI/Oアドレス94からのINで行われます。
このときにアドレス94の出力(IC4、74HC373)がアクティブになっていると、PIC18F2550からのデータ出力とぶつかってしまいますから、出力禁止にしておかなければなりません。I/Oアドレス98のビット2出力をHにしておきます。
PIC18F2550からのSTROBE信号は、I/Oアドレス98のビット0からの入力で確認されます。
このラインがL(0)になったら、I/Oアドレス94からデータを読み込みます。
READY/BUSY信号はI/Oアドレス98のビット0出力です。
PIC18F2550からのデータ読み込み動作に入る前に、I/Oアドレス98から’FF’を出力して、IC4の出力禁止とREADY出力にしてあります。
データを読み込むよりも前に、BUSY(アドレス98のビット0=0)を出力しているのは、Aレジスタにデータを読み込まなくてはいけないからです。
とはいえ、結局READYを出力するのにAレジスタが必要になりますから、受信したデータは一時Cレジスタに退避させます。
●8ビットパラレルデータ伝送(PIC18F2550プログラム)
こちらはPIC18F2550のプログラムです。
Z80のプログラムと同じことをやっているのですが、PIC18F2550のほうがはるかに短いプログラムで済んでいます。
PICのアセンブラ(機械語の命令)はかなり評判が悪いようですが、こうやって比べてみると、I/O制御に適した命令機能をもっていることがわかります。
; ;data out to cpu ; dtoutsub btfss PORTA,1 goto dtoutsub movwf PORTB bcf PORTA,0 dtoutsub2 btfsc PORTA,1 goto dtoutsub2 bsf PORTA,0 return ; ;data in from CPU to READBF ; dtin movf PORTB,w bcf PORTA,2;set busy movwf INDF2 dtin3 btfss PORTA,3;if strobe off goto dtin3 bsf PORTA,2;set ready return ;
PIC18F2550の側は、パラレルデータの入力、出力にPORTBを使います。
PIC18F2550からZ80の側にパラレルデータを出力する(data out)場合には、PORTAのビット0をSTROBE出力に使います。
bcf PORTA,0でSTROBE on、bsf PORTA,0でSTROBE offです。
bcfはビットクリア、bsfはビットセット命令です。
Z80からのREADY/BUSYはPORTAのビット1に入力されます。
btfssは指定したビットがセットされていたら、次の命令(多くはgotoが使われる)をスキップする命令です。
btfscはその逆に、指定したビットがクリアされていたら、次の命令をスキップする命令です。
movwf PORTBは、wレジスタの値をPORTBにmoveする(wレジスタの値がPORTBから出力される)ために使われています。
PICにはOUT命令、IN命令はありません。
I/Oポートもレジスタとして扱われます。
出力の向きに設定したポートレジスタに値をmoveすることで出力が行われます。
逆に入力の向きに設定したポートレジスタからwレジスタに値をmoveすることで、INと同様の働きになります。
movf PORTB,wは、PORTBからwレジスタに入力値を読み込むために使われています。
PIC18F2550がZ80からのデータを受け取る(data in)場合には、PORTAのビット2をREADY/BUSY出力に使います。
PORTAのビット3には、Z80からのSTROBE信号が入力されます。
data in プログラムには、Z80CPU側からのSTROBEを確認するところがなくて、いきなりデータを読み込んでいますが、STROBEを確認していないのではなくて、このサブルーチンをCALLしている親プログラムで確認しています。
●4ビットパラレルデータ伝送(TK80モニタプログラム)
さていよいよ8ビットデータ伝送を4ビット×2データ伝送に直しての動作テストです。
といってもそれほどむつかしいことではありません。
ただすこし面倒なだけです。
4ビットで送受信しますからデータのビット0〜ビット3だけを使います。ビット4〜7は使いません。
; ;SERIAL OUTPUT ROUTINE ; 027C 4F SOUT:MOV C,A 027D DB98 SOUT2:IN 98 027F E602 ANI 02 0281 CA7D02 JZ SOUT2 0284 CD2603 CALL SOUTSB 0287 3EF9 MVI A,F9; I/Oaddress 94 "out" & STROBE ON 0289 D398 OUT 98 028B DB98 SOUT3:IN 98 028D E602 ANI 02 028F C28B02 JNZ SOUT3 0292 3EFB MVI A,FB; I/Oaddress 94 "out" & STROBE OFF 0294 D398 OUT 98 0296 C9 RET ; ;SERIAL INPUT ROUTINE ; ORG $02A0 ; 02A0 DB98 SIN:IN 98 02A2 0F RRC 02A3 DAA002 JC SIN 02A6 3EFE MVI A,FE;BUSY 02A8 D398 OUT 98 02AA DB94 IN 94 02AC E60F ANI 0F 02AE 4F MOV C,A 02AF 3EFF MVI A,FF;READY 02B1 D398 OUT 98 02B3 DB98 SIN1:IN 98 02B5 0F RRC 02B6 DAB302 JC SIN1 02B9 3EFE MVI A,FE 02BB D398 OUT 98 02BD DB94 IN 94 02BF 07 RLC 02C0 07 RLC 02C1 07 RLC 02C2 07 RLC 02C3 E6F0 ANI F0 02C5 B1 ORA C 02C6 4F MOV C,A 02C7 3EFF MVI A,FF 02C9 D398 OUT 98 02CB 79 MOV A,C 02CC C9 RET ; ; 0326 79 SOUTSB:MOV A,C 0327 D394 OUT 94 0329 3EF9 MVI A,F9 032B D398 OUT 98 032D DB98 SOUTSB2:IN 98 032F E602 ANI 02 0331 C22D03 JNZ SOUTSB2 0334 3EFB MVI A,FB 0336 D398 OUT 98 0338 DB98 SOUTSB3:IN 98 033A E602 ANI 02 033C CA3803 JZ SOUTSB3 033F 79 MOV A,C 0340 0F RRC 0341 0F RRC 0342 0F RRC 0343 0F RRC 0344 D394 OUT 94 0346 C9 RET
8ビットデータを1回で送信していたところを、2回の繰り返しに変更します。
TK80モニタプログラムをそのまま書き直すと、入力ルーチン(SIN)の開始アドレスがオリジナルと違ってきてしまいますから、一部をサブルーチンにしています(SOUTSB)。
最初は下位4ビットを送ります。
送信する場合はそのまま出力するだけです。
次に上位4ビットを出力するために、RRC命令(右ローテイト)を4回繰り返して上位4ビットのデータを下位4ビットに移動します。
そのようにしておいてから、データを出力します。
データを受信する場合は、8ビットで受け取ることになります(ただし上位4ビットは無意味です)から、受け取ったあと、上位4ビットを捨てるためにANI 0Fを使って、上位4ビットを’0’にしてからワークレジスタに保存します。
次に上位4ビットのデータがやはり下位4ビットのデータとして送られてきますから、RLC命令(左ローテイト)を4回使って、下位4ビットのデータを上位4ビットに移動します。
そのあとで、ANI F0で下位4ビットを’0’にしてから、先に受信した下位4ビットデータとOR命令で合成して、もとの8ビットデータに戻します。
●4ビットパラレルデータ伝送(PIC18F2550プログラム)
今回8ビットパラレルデータ伝送を4ビットデータ伝送に変更する目的はPIC18F14K50を使うためです。
しかしいきなりPIC18F14K50のためのプログラムを書いてしまって、それでテストをする、というのは余りに乱暴です。
なにしろPIC18F14K50はまだ使ったことがありません。
今回使ってみるのがはじめてですから、いきなりぶっつけ本番で試したりしたら、どんなトラップにはまってしまうかわかったものではありません。
おお。神よ。
なんと賢明な判断であったことか。
そのように慎重にことを運んでさえ、見事に底無し沼のトラップにはまってしまったのですから。
それはともかく、PIC18F2550では8ビットデータ伝送は動作を確認済みです。
ここはまず、回路もそのまま使うことにして、データ伝送部の上位4ビットも配線済みのまま、プログラムだけ上位4ビットを使わない、ということで動作テストを行いました。
そのようにすれば、プログラム変更の結果、うまく動作しなかった場合でも、もとの8ビットに戻して再確認などをすることもできます。
という考えから、まずはPIC18F2550を使って4ビットデータ伝送のテストをしてみることにしました。
これがPIC18F2550の4ビット出力および入力プログラムです。
考え方はTK80モニタプログラムの変更についての考え方と全く同じです。
; ;data out to CPU ; dtoutsub btfss PORTA,1 goto dtoutsub movwf datawk movwf PORTB;low 4bits out bcf PORTA,0 dtoutsub2 btfsc PORTA,1 goto dtoutsub2 bsf PORTA,0 dtoutsub3 btfss PORTA,1 goto dtoutsub3 rrncf datawk rrncf datawk rrncf datawk rrncf datawk,w movwf PORTB;high 4bits bcf PORTA,0 dtoutsub5 btfsc PORTA,1 goto dtoutsub5 bsf PORTA,0 return ; ;data in from CPU to READBF ; ; dtinsub movf PORTB,w andlw 0f movwf datawk bcf PORTA,2 dtinsub1 btfss PORTA,3 goto dtinsub1 bsf PORTA,2 dtinsub2 btfsc PORTA,3 goto dtinsub2 movf PORTB,w bcf PORTA,2 movwf datawkh4 rlncf datawkh4 rlncf datawkh4 rlncf datawkh4 rlncf datawkh4,w andlw 0f0 iorwf datawk,w dtinsub3 btfss PORTA,3 goto dtinsub3 bsf PORTA,2 return
このようにして、TK80モニタプログラムとPIC18F2550のプログラムの両方を4ビットデータ伝送に書き直して動作テストを行って、8ビットの場合と同じように動作することを確認いたしました。
すると、次はいよいよ、PIC18F2550のプログラムを、PIC18F14K50に移植しての動作テストです。
2010.5.17upload
前へ
次へ
ホームページトップへ戻る