PICBASICコンパイラ
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
まるでインタプリタ。でもコンパイラです。超カンタン超シンプルです。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
[第103回]
●SDカードIF(23)ND80Z3.5に接続(16)解決編
やっと着地点まで来ました。
なぜ”FF”エラーになってしまうのか、その原因の解明です。
ここはなかなか説明が難しいです。
自分ではわかっています。
しかしそれを図に描いて示そうとしますといまひとつうまく説明ができません。
わかりにくいかもしれませんがそこはお許しを。
今までのところで書いてきましたように”FF”になってしまうのはどうやらND80Z3.5側のプログラムとPIC18F2550のプログラムのタイミングが食い違ってしまうかららしいということがわかってきました。
本来ならば片方が「送信」ならばもう片方は「受信」であるはずです。
両者のプログラムはそのように設計してあります。
電話のように送信と受信が同時に行なわれることはありません。
こちらが送信のときは相手は受信でなければなりません。
こちらが送信のときに相手がそれを検知して受信に切り換えるというシステムでもありません。
ですからなんらかの理由でタイミングが合わなくなってしまうと双方が「送信モード」あるいは「受信モード」になってしまいます。
なぜそういうプログラムになっているかというとそれはひとえにソフトウェアの負担を軽くするためです。
コマンドによって双方がそれぞれ「送信モード」であるべきタイミングと「受信モード」であるべきタイミングはあらかじめプログラムで決定されていますから本来はそれが食い違うはずはない(はずでありました)。
万一それが食い違ってしまった場合にも正常なタイミングに復帰できるようにプログラムを修正しました([第101回])。
「対症療法的」な対策です。
ですからとりあえず”FF”問題はクリアできたのですが。
あれこれ思考を重ねていく中でなぜそうなるのかという原因がわかりました。
「わかったぞ!原因はそこだったんだ!」
謎解きの醍醐味であります。
というと格好いいのですが、要するに当初のプログラム設計にとんでもないアナがあったわけで別に自慢できることでもなんでもありません。
問題はPIC18F2550のリセット直後の双方のプログラムのタイミングにありました。
ND80Z3.5と接続して動作テスト中のPICSDカードIFシステムは先にND80Z3.5側のプログラムを実行します。
ND80Z3.5のプログラムは実行を開始すると最初にPICSDカードIFボードのPIC18F2550をリセットします。
そしてPICSDカードIFボードが接続されていてそれが正しく機能しているかどうかを確認し双方の送受信のタイミングを合わせます。
そこのところにアナがありました。
下は当初私が考えていた双方のプログラムの流れです。
ND80Z3.5の82C55のPC2はPIC18F2550のRESET端子(MCLR)につながっています(この部分の回路図は[第85回]にあります)。
PC2〜PC0のポートの向きは「出力」に固定されています。
ND80Z3.5側のプログラムがスタートすると最初に十分な期間PC2をLにしたあとHにします。
PC1はND80Z3.5側が送出するクロックです。
送受信のためのクロックはND80Z3.5側からしか出力されません。
ND80Z3.5はPC0から送信データを出力します。
このラインはPIC18F2550のRC0につながっていてND80Z3.5側からのデータを受信します。
PC7とPC6のポートの向きは「入力」に固定されています。
PC7はPIC18F2550からのREADY_/BUSY信号を受信します。
PC6はPIC18F2550からの送信データを受信します。
上記の4本のラインはプログラムの起動時には双方のタイミングを合わせるためと、PIC18F2550が存在していてそれが正しく動作するかどうかを確認するために使われます。
(1)リセット後にPIC18F2550はTRISA命令でPORTAの向きを「出力」に設定します。
PIC18F2550はリセット後はPOATAは「入力」になります。
82C55のラインはプルアップされているのでPC7とPC6はHですがこれはPIC18F2550からHが出力されているからではなくてRA3、RA2が「入力」でラインがハイインピーダンスだからです。
TRISAの設定によってRA3とRA2はLになります(と考えたところにアナがありました)。
わかっていたつもりだったのですが、ついうっかりしてPIC18F2550も82C55と同じようにポートの向きを出力に設定するとポートの出力はLになる、と考えてしまいました。
(2)PORTAのRA3出力とRA2出力をHにします。
ここでもうっかりしてまずいプログラムを書いてしまいました。
本来はTRISAの実行直後にPORTAのRA3、RA2をHにすべきでした。
そこにうっかりして他の命令をはさんでしまったためRA3とRA2がHになるまでに少し時間がかかっていました。
後になってわかったことなのですが、それが”FF”問題の原因となったのでした。
下は修正前のプログラムです。
movlw 7f;8MHz movwf OSCCON clrf TRISA movlw 01;RB0=in movwf TRISB movlw 03 movwf TRISC movlw 0ff movwf PORTC movwf PORTA |
CLRF TRISAからMOVWF PORTAまで7命令あります。
CLOCKは8MHzなので1命令の実行時間は4/8=0.5μsです。
リセット後にRA7、RA6は3.5μsの期間Lになります。
わずかな時間なのですが、これが「落とし穴」でした。
上のタイミング図に戻ります。
(3)PIC18F2550はその後RC1とRC0(82C55のPC1とPC0)の状態を確認しそれが共にLならば初期的な設定を実行します。
この間は約300μsです。
(4)それが済むとPIC18F2550はRA3をLにします(RA2はHのままです)。
(5)ND80Z3.5側はPC7=0、PC6=1を確認するとPC1とPC0をHにします。
(6)PIC18F2550はRC1=RC0=1を確認するとRA3をHにします。
(7)ND80Z3.5側はPC7=PC6=1を確認するとPC1とPC0をLにします。
以後はND80Z3.5側のPC1とPC0がL出力になり、PIC18F2550のRA3とRA2がH出力になるはず、だったのですが。
ひょっとして。
もしもリセットしてもPIC18F2550のポート出力はリセットされないとしたならば。
そしてもしもリセット前のPIC18F2550のRA3出力がL、RA2出力がHになっていて、そこでリセットをかけたとしたならば。
その考えが頭に浮かんだ時点では、それは推測、ただの仮定に過ぎなかったのですが、いろいろ試していくうちにどうもそうに違いないという確信に変わってきました。
とりあえずは今は仮定としてそういうことだとすると、上記のタイミングは下のようになる可能性があります。
リセット直後からND80Z3.5側はPC7=0、PC6=1をチェックし続けます。
ここにも対策すべきところはありました。
当初はPIC18F2550はPORTAの向きを設定後にRA3=0、RA2=1を出力するまではRA3=RA2=1かRA3=RA2=0のどちらかだと思い込んでいました。
以前にPICの動作については確認して理解していたはずなのですが、なんですかねえ、しっかりすっかり忘れてしまっておりました。
実に困ったことです。
上の仮定に従った場合(1)TRISAの実行によってRA3=0、RA2=1になります。
すると(5)ND80Z3.5がそれを認識してPC7=1、PC6=1にします。
PIC18F2550はまだTRISAを実行しただけの段階ですから次に(2)RA3=1、RA2=1にします。
(1)の直後に(2)が実行されていればRA3=0の期間はほんの一瞬(0.5μs)ですから(5)が実行される可能性はかなり低くなるはずですが、上に書きましたようにその期間は3.5μsですからND80Z3.5側のプログラムがその「穴」を検知して(5)を実行する可能性はかなり高くなります。
(7)そしてND80Z3.5は(2)の状態を確認するとPC1=0、PC0=0にします。
(3)(4)PIC18F2550は(7)を確認すると初期設定を実行し約300μs後にRA3=0にします。
この後はPIC18F2550はずっと(6)RC1=1、RC0=1になるのを待ち続けることになります。
このように考えると確かにここで「食い違い」が発生することになります。
しかし本当にそうなのか。
実のところPIC18F2550のI/Oポートはリセット後はどうなるのか。
そしてそもそも上図のようなことが本当に起こり得るのか。
今回は解決編のつもりだったのですがちょっと長くなってしまいましたので、今回はここまでにします。
次回に続きます。
PICBASICコンパイラ[第103回]
2023.11.19upload
前へ
次へ
ホームページトップへ戻る