標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第583回]
●PICSTBがおかしい
前回、PIC18F14K50からZ80CPU側に232C受信データを渡しているところをロジアナで記録した波形を見まして、おかしいところがあることに気が付きました、と書きました。
まずはそのことについて説明をいたします。
これは前回最初にお見せした波形です。
16,17と続くデータの、 ,1 の部分を渡しているところです。
おかしなところというのは、図の矢印で示した@の立下り部分です。
この信号はPIC18F14K50がZ80にデータを渡すときに、そのデータをセットしたことをZ80に示すためのSTB信号です。
処理の流れから、このデータは232C受信データなのですが、ここでデータがセットされるのはあきらかに間違っています。
@の立ち下りは、その上の232Cセレクト信号が立ち上がったあとのタイミングになっています。
なぜ?
おかしいのはそこなのです。
PICSTB信号は、232Cセレクト信号の立ち下りを見て、出力されるべきなのです。
次のデータを受け取るために232Cセレクト信号が立ち下るのは、Aのタイミングですから、ほんとうはAのあとで、@の立ち下りが来なければいけないはずです。
もうひとつおかしいところがあります。
Bの立ち下りも、@と同じ理由でおかしいのです。
このときは、受信バッファにデータが残っていなかったらしく、受信バッファエンプティを返しているために、PICSTBは15μsec程度で立ち上がっています。
この受信バッファエンプティの信号も、本当はCのタイミングが正しいのです。
なぜかBで余計な応答をしてしまっています。
なぜか、と書きましたがもちろん今はその理由はわかっています。
●PIC18F14K50のデータ送出プログラムに甘いところがありました
PIC18F14K50のデータ送出ルーチン(dtoutsub)のソースリストです。
このリストは上で指摘した問題点を修正したあとのものです。
dtoutsub movwf datawk btfsc PORTC,4 iorlw 10;rc4=1 (232cerror none) btfss PORTC,4 andlw 0f;rc=0 (232cerror) dtoutsub1 btfss PORTC,5;wait till cpu READY goto dtoutsub1 movwf PORTC;low 4bits out bcf PORTB,4; STROBE out dtoutsub2 btfsc PORTC,5; wait till cpu BUSY goto dtoutsub2 bsf PORTB,4; STROBE off ; High 4 bits data out rrncf datawk rrncf datawk rrncf datawk rrncf datawk,w btfsc PORTC,4 iorlw 10;rc4=1 (232cerror none) btfss PORTC,4 andlw 0f;rc=0 (232cerror) dtoutsub3 btfss PORTC,5; wait till cpu ready goto dtoutsub3 movwf PORTC;high 4bits out bcf PORTB,4; STROBE out dtoutsub4 btfsc PORTC,5; wait till cpu BUSY goto dtoutsub4 bsf PORTB,4; STROBE off dtoutsub5 btfss PORTC,5;wait till cpu ready & 232c off goto dtoutsub5 btfss PORTC,7 goto dtoutsub5 return
このことに気が付く前は、一番最後の
btfss PORTC,7
goto dtoutsub5
が無かったのです。
当初は、この部分が無かったために、232Cセレクト信号の立ち上がりを確認しないでリターンしていました。
232Cセレクト信号もじきに立ち上がるのですが、PIC18F14K50は何しろクロックが48MHzですから、実に速いのです。
前回お見せしたフローチャートをあっという間に一巡してしまって、まだ232Cセレクト信号が立ち上がる前に、次の232Cセレクト信号のチェックルーチンにエントリしてしまっていたのです。
Bの立ち下りが発生してしまったのもまったく同じ理由からでした。
そして、問題のデータの欠落部分です。
Dの立ち下りが誤りであることは上で説明した理由と全く同じなのですが、今度はまだ受信データが残っているために、Z80がそれを引き取るまでずっと待っています。
Z80CPU側は、かなり時間が経ってから、約120μsec後に、Z80BUSY信号をアクティブにして、データを引き取っています。
ところが良く見ますと、232Cセレクト信号は上がったままです。
ということはZ80CPUは、このときのデータは232C受信データではなくて、USB(HID)経由でWindowsパソコンから送られてきたデータとして受け取っているらしいことになります。
しかし、PIC18F14K50の側は、232C受信バッファのデータを渡しているのです。
なぜこのような食い違いが起きてしまったのでしょうか。
じつは、前回の出力データの説明にもありましたように、このときのコード[37]つまり文字’7’が、Z80BASICで232C受信データを格納していたA$に39バイト目のデータとして入れられたので、一旦READ #1命令が終了して、次の処理に移っていたのです。
Z80BASICは、実行中にWindowsパソコンのキーボードから[Ctrl][B]を入力することでブレイクさせて、実行を中止することができます。
その機能のために、Z80BASICでは、各行の先頭部分で毎回ブレイクキーの入力の有無をチェックしています。
上のロジアナの波形にあった、Windowsパソコンからのデータとして受け取っているのは、そこだったのです。
しかしブレイクチェックルーチンではブレイクコード(00)にしか反応しませんから、そこで受け取ったコード(2C)は結局捨てられてしまったのです。
ところで、前回お見せしましたように、A$に39バイトのデータが溜まる以前にも、ひんぱんにREAD #1が終了して次の処理に移っていたはずなのに、なぜ、39バイトのデータが溜まったときに限って、上で説明したようなデータの欠落が起きたのでしょうか。
これには、かなり悩みました。
なぜだろうか?
たまたま、とか偶然に、とかといって片付けるにはちょっと無理があります。
何か理由があるはず。
やっと、そのわけがわかりました。
その理由は、READ #1の処理ルーチンの仕組みにありました。
前回説明しましたように、READ #1命令は、そこで受信待ちでハングアップしてしまわないように、受信バッファエンプティを受け取ったときは、すぐにリターンします。
受信データがあるときは、文字変数にそのデータを追記していきますが、文字変数に39バイトのデータが格納されると、データの受け取り処理を中断して、READ #1を一旦終了してしまいます。
参考までに、Z80BASICのREAD #1部分のプログラムリストです。
;;; 3946 13 RDURA:INC DE 3947 CD262A CALL ICALC 394A 7D LD A,L 394B FE01 CP 01 394D C21F3A JP NZ,ER3E;=62 3950 CD0E3A CALL RDHNS 3953 C21F3A JP NZ,ER3E 3956 E5 PUSH HL 3957 CD0E3A CALL RDHNS 395A FEF2 CP F2 395C C21F3A JP NZ,ER3E 395F DDE1 POP IX 3961 DDE5 PUSH IX;A$ 3963 E5 PUSH HL;A% 3964 4E LD C,(HL) 3965 23 INC HL 3966 46 LD B,(HL) 3967 DDE5 PUSH IX 3969 E1 POP HL 396A 03 INC BC 396B 79 LD A,C 396C B0 OR B 396D CA7D39 JP Z,SIN2;A%=-1 3970 0B DEC BC 3971 79 LD A,C 3972 B0 OR B 3973 CA7C39 JP Z,SIN1 3976 E1 POP HL 3977 DDE1 POP IX 3979 C3EE2F JP STEND 397C 77 SIN1:LD (HL),A 397D 7E SIN2:LD A,(HL) 397E FE27 CP 27 3980 D2A839 JP NC,SINFUL;A$=FULL 3983 23 INC HL 3984 D5 PUSH DE 3985 1600 LD D,00 3987 5F LD E,A 3988 19 ADD HL,DE 3989 47 LD B,A 398A 3E27 LD A,27 398C 90 SUB B 398D CDB439 CALL RDSB 3990 D1 POP DE 3991 E1 POP HL 3992 DDE1 POP IX 3994 DD7000 LD (IX+00),B 3997 CAAD39 JP Z,SINEND 399A 78 LD A,B 399B FE27 CP 27 399D CAAB39 JP Z,SINFUL2 39A0 3EFF LD A,FF 39A2 77 LD (HL),A 39A3 23 INC HL 39A4 77 LD (HL),A 39A5 C3EE2F JP STEND 39A8 E1 SINFUL:POP HL 39A9 DDE1 POP IX 39AB 0628 SINFUL2:LD B,28 39AD 70 SINEND:LD (HL),B 39AE 23 INC HL 39AF 3600 LD (HL),00 39B1 C3EE2F JP STEND ; 39B4 08 RDSB:EX AF,AF' 39B5 C5 RDSB2:PUSH BC 39B6 06EB LD B,EB 39B8 78 LD A,B 39B9 D398 OUT (98),A 39BB DB94 RDSB3:IN A,(94) 39BD E620 AND 20 39BF C2BB39 JP NZ,RDSB3 39C2 3E0A LD A,0A;WAIT ABOUT 20MICROS 39C4 3D RDSB32:DEC A;(4) 39C5 C2C439 JP NZ,RDSB32;(10) 39C8 DB94 IN A,(94) 39CA E620 AND 20 39CC C2F739 JP NZ,RDSB4 39CF DB94 IN A,(94) 39D1 E610 AND 10 39D3 F5 PUSH AF 39D4 CDA706 CALL RSIN 39D7 3EEF LD A,EF 39D9 D398 OUT (98),A 39DB F1 POP AF 39DC CAFD39 JP Z,SINER;=73 39DF 79 LD A,C 39E0 C1 POP BC 39E1 FE0A CP 0A 39E3 C8 RET Z 39E4 FE0D CP 0D 39E6 CAB539 JP Z,RDSB2 39E9 77 LD (HL),A 39EA 23 INC HL 39EB 04 INC B 39EC 08 EX AF,AF' 39ED 3D DEC A 39EE CAF539 JP Z,RDSB33 39F1 08 EX AF,AF' 39F2 C3B539 JP RDSB2 39F5 3C RDSB33:INC A;reset zf 39F6 C9 RET 39F7 3EEF RDSB4:LD A,EF 39F9 D398 OUT (98),A 39FB C1 POP BC 39FC C9 RET ; 39FD F1 SINER:POP AF;DUMMY 39FE F1 POP AF;DUMMY 39FF D1 POP DE 3A00 E1 POP HL 3A01 71 LD (HL),C 3A02 23 INC HL 3A03 3600 LD (HL),00 3A05 3EEF LD A,EF 3A07 D398 OUT (98),A 3A09 3E49 ER49:LD A,49 3A0B C33D31 JP ERRDP
[以下の説明部分を書き直しました(2010.8.15)]
文字変数に39バイトのデータが入れられると、それ以上はその文字変数にデータを入れることはできません(Z80BASICの文字変数は39バイトの固定長です)。
そこでその文字変数のデータを処理できるようにするために、一旦READ #1を終了します。
このことは、PIC18F14K50の232C受信バッファにデータが残っていても、残っていなくても、それとは関係なしにZ80BASIC側の事情(文字変数に39バイトのデータが格納されたこと)によって発生します。
もしまだ受信バッファにデータが残っている場合には、PIC18F14K50は続いて残っているデータを送出しようとすることになりますが、Z80BASIC側は、文字変数のデータを処理して、ふたたびREAD #1ルーチンにエントリしてくるまでの間は、その受信データを引き取ることはできません。
そこで、READ #1ルーチンでは、受信データを1バイト引き取るごとに、232Cセレクト信号をアクティブにするようにしているのです。
PIC18F14K50は、232Cセレクト信号が立ち下がったら、Z80側に受信データを1バイト送り出します。
READ #1ルーチンで、232Cセレクト信号をアクティブ(出力L)にしているところは、上のリストのアドレス39B9です。
I/Oアドレス98のビット2が、232Cセレクト信号です。
この出力ラインはPIC18F14K50のPORTCのビット7につながっています。
232CセレクトラインをOFF(出力H)にしているところは、アドレス39D9、39F9です。
このラインを1バイト受信するごとにアクティブにして、PIC18F14K50からのデータ送出をコントロールしていたつもりだったのですが、PIC18F14K50のプログラムで、232Cセレクト信号がOFF(H)になるのを確認しないで、Z80へのデータ送出ルーチンからリターンしていたために、Z80側が受け取った1バイトのデータの処理を完了して232CセレクトラインをHにするよりも前に、ふたたびPIC18F14K50のデータ送出ルーチンが実行されていました。
Z80BASICの側では、まだ文字変数に39バイトのデータが格納されるまでの間は、引き続きREAD #1ルーチンの中で、次のデータを受け取りますから、PIC18F14K50が、先にデータを送出するようにしていても、そこでは問題は発生することなく、データの受け渡しが行われます。
もしPIC18F14K50の232C受信バッファにデータが残っていない場合には、さきほどのロジアナ波形の矢印Bのように、受信バッファエンプティの誤出力になりますから、わずか15μsecの期間だけアクティブになるだけです。
PIC18F14K50のクロック48MHzは非常に高速ですが、Z80は6MHzですから、それに比べればかなりゆっくりしています。
矢印BのパルスはZ80BASICでは認識されることなくパスされてしまっているのですが、もしもZ80の処理がもう少し速くて、Bのパルスを認識していたとしても、その場合には、やっぱり受信バッファエンプティとして処理されますから、したがって、この場合にもなんの問題も発生しません。
結局、まだPIC18F14K50の受信バッファに、送出されていないデータが残っているときに、文字変数にデータが39バイト格納されて、そこでREAD #1が終了した時に限って、PIC18F14K50は次のデータをセットして、それをZ80側が引き取るまでスタンバイすることになり、そしてそのときには、Z80BASICではブレイクコードのチェックが行われるために、上で説明した「食い違い」によって、データの欠落が発生することになったのです。
文字変数データに39バイトのデータが格納されてREAD #1が終了したときに、たまたまPIC18F14K50の232C受信バッファが空になっていた場合には、矢印Bの受信バッファエンプティが出力されますが、これは既に説明しましたように、出力されるタイミングが速すぎてZ80側では認識できませんから、そのままパスされてしまいます。
したがって、このときには、文字変数が39バイトになっても、データの欠落はおこりません。
データの欠落は、文字変数にデータが39バイト入れられた直後に発生していましたが、しかし、文字変数にデータが39バイト入れられた直後でも、発生していないところもありましたが、そのときは、たまたま受信バッファが空になったときだったのです。
[ここまで2010.8.15書き直し]
プログラム修正後の波形です。
PICSTBの誤出力は無くなっています。
もちろん、データの欠落は発生しなくなりました。
>. 10 A%=0 20 READ #1,A$,A% 30 IF A%<1 GOTO 20 40 PRINT A$ 50 GOTO 10 >r. 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,1 6,17,18,19,20,21,22,23,24,25,26,27,28,2 9,30,31,32,33,34,35,36,37,38,39,40,41,4 2,43,44,45,46,47,48,49,50,51,52,53,54,5 5,56,57,58,59,60,61,62,63,64,65,66,67,6 8,69,70,71,72,73,74,75,76,77,78,79,80,8 1,82,83,84,85,86,87,88,89,90,91,92,93,9 4,95,96,97,98,99,100,101,102,103,104,10 5,106,107,108,109,110,111,112,113,114,1 15,116,117,118,119,120,121,122,123,124, 125,126,127,128,129,130,131,132,133,134 ,135,136,137,138,139,140,141,142,143,14 4,145,146,147,148,149,150,151,152,153,1 54,155,156,157,158,159,160,161,162,163, 164,165,166,167,168,169,170,171,172,173 ,174,175,176,177,178,179,180,181,182,18 3,184,185,186,187,188,189,190,191,192,1 93,194,195,196,197,198,199,200,201,202, 203,204,205,206,207,208,209,210,211,212 ,213,214,215,216,217,218,219,220,221,22 2,223,224,225,226,227,228,229,230,231,2 32,233,234,235,236,237,238,239,240,241, 242,243,244,245,246,247,248,249,250,251 ,252,253,254,255,end
2010.8.14upload
2010.8.15一部更新
前へ
次へ
ホームページトップへ戻る