RA4のオープンドレインが分ってもまだ安心は出来ません。
RA4は更なる罠を隠し持っています。
下の回路図を見てみましょう
オープンドレイン出力のRA4をプルアップして正論理でLEDを光らすというものです。
一見これで何の問題もなさそうです。
ためしに
PORTA = 0x1F;
としてみましょう。(プログラムはCで記述。コンパイラ:HI-TECH C PRO (Lite mode) )
バッチリ全LEDが点灯しました。
次に、30[ms] 後にLED0だけを消灯するために、
PORTA = 0x1F;
としてみます。
__delay_ms(30);
RA0 = 0;
(゜Д゜)!?
そうすると、なぜかLED0だけでなく、LED4も消えます。
RA4などいじっていないのに・・・
これは8ビットシリーズのPIC特有の現象です。
AVRマイコンなどではこのようなことは起こりません(使ったことはないけど^^;)
一体何が起こっているのでしょうか
実は、
RA0 = 0;
という文は、一見RA0しか操作していないように見えるのですが、実はPORTAの全てのピンを書き直しています。
8ビットマイコンは1ビット単位の処理はできず、8ビット単位でしか処理できないのです。
一旦PORTAの全ピンを読込み、その値に対して演算してビット0だけを書き換え、またPORTAに戻します。
つまり、この文の実際の動作は、
char temp = PORTA; //PORTAを読込む
となります。
temp &= 0xFE; //ビット0だけをクリア
PORTA = temp; //PORTAに書き込む
この1文目が重要です。PORTAは出力ポートなのにあたかも入力ポートかのように読込んでいます。
この時のRA4ピンの電圧に注目しましょう。
これを説明するためにオープンドレイン出力であるRA4ピンの動作をスイッチで示したのが以下の図になります。
この図でRA4は何Vでしょう?
LEDの電圧降下分である2V弱程度であることが分ります。つまり、"LOW (0) " です!!!
なんということでしょう!
"1"
を出力しているのに、入力として読むと
"0"なのです!
つまり、RA0を書き換えるとき、一旦PORTAを読込むが、その時にRA4について実際の出力とは異なる値を読み、
そのまま書き込んでしまうためRA4が書き換わってしまうのです。
ちなみにこれはRA4ピンでなくても出力ピンに低いインピーダンスの負荷をつないでいるときに起こります。
これを防止する最も確実な手段は1ビット単位での書き換えをしないことです。つまり、
RA0 = 0;
という文は使わないこと。代わりにあらかじめ、
PORTA用変数
char latA
を用意しておき、
latA
を自力で書き換えたあと、最後にPORTAを丸ごと書き換えます。
つまり、上記のプログラムは
char latA;
とします。ものすごく面倒ですが^^;
latA = 0x1F; //一旦latAに書き込む
PORTA = latA; //PORTAを丸ごと書き換える
__delay_ms(30);
//一旦latAを書き換える
latA = (latA & 0xFE) | 0x00; //ビット0に値をセット
PORTA = latA; //PORTAを丸ごと書き換える
ではなぜ8bitシリーズのPIC以外のマイコンではこの現象が起こらないのでしょうか?
PIC以外のマイコンでも8bit単位でしか操作できないというのはどのマイコンも同じです。
実は、PIC以外のマイコンには上記のPORTA用変数 char latA
が
もともとついているのです。
これをDATAラッチといいます。
なので、単に
_LATA0 = 0;
のようにするだけで、上の
char latA
を使ったプログラムと同じことをするのです。
つまり、8bitシリーズのPICには
Microchipの陰謀により、DATAラッチがないため、このような現象が起こるのです。
(16bitシリーズのPIC (dsPICやPIC24F) にはDATAラッチがあります。)