標準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一部更新

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