311.PIOで入出力する(PIC16F873)


2001/12/12 【ソフトウエア編TOPに戻る】

前回は、PIC16F84Aを使ったPIOのプログラム例をご紹介しました。今回は、同じことをPIC16F873を使ってやってみます。

PIC16F873PIC16F84Aに比べると、A/D変換、タイマー機能、通信機能、PIOポート数など、あらゆる面で多機能になっています。

PICにはいくつかのシリーズがあり、それぞれに多くのファミリーがラインナップされていますが、基本的なアーキテクチャは共通化されていて、プログラムの移植性も非常に高いものです。しかし、デバイスの種類によって付いている機能や付いていない機能があり、それらは一種のクセを生みます。つまり、あるプログラムを違う種類のPICで使おうする時には、そのクセをつかみ、ちょっとだけプログラムを手直ししてあげたりする必要があります。

今回は、PIC16F84A用に作ったプログラムpiotes1A.asmを、PIC16F873用に作り直してみて、その両者の違いを実際にみてみましょう。


311−1.PIC16F873用のPIO入出力プログラムpiotes1B.asm

さて、今回のプログラムも、前回ご紹介したPIC16F84Aのプログラムと基本的には同じです。なので、いきなり実際のプログラムをご紹介してしまいます。しかしちょっとだけ違う点があります。ここでは、そのPIC16F84APIC16F873のプログラムの違いだけを見てみましょう。

ここをクリックすると以下のソースコードをダウンロードできます。piotes1B.asm

 

;**********************************************************************
;PIOTES1B                                                    2001.11.30
;DEVICE : PIC16F873
;CLOCK : 20MHz
;PORT-Aの入力データをPORT-Bに出力する
;**********************************************************************
       list p=16F873
       #include <p16F873.inc>

       __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC & _LVP_OFF

;**********************************************************************
       ORG     00H            ; processor reset vector
       GOTO    MAIN           ; go to beginning of program

MAIN   BSF     STATUS,RP0     ;メモリーバンクを1にセット
       MOVLW   06H            ;Wレジスタに06Hをセット
       MOVWF   ADCON1         ;ADCON1に06Hをセット PORTA全てデジタル
 
       MOVLW   0FFH           ;WレジスタにFFHをセット
       MOVWF   TRISA          ;TRISAにFFHをセットPORT-Aを入力にセット
       CLRF    TRISB          ;TRISBをクリア PORT-Bを出力にセット
       MOVLW   80H            ;Wレジスタに80Hをセット
       MOVWF   OPTION_REG     ;OPTION_REGに80Hをセット PORT-B PULL UPなし
       BCF     STATUS,RP0     ;メモリーバンクを0にセット

;***********************************************************************
;PORT-Aの入力データをPORT-Bに出力
;***********************************************************************
LOOP
       MOVF    PORTA,W        ;WレジスタにPORTAのデータ取り込む
       MOVWF   PORTB          ;PORTBにPORTAのデータを出力する
       GOTO    LOOP           ;ラベルLOOPにジャンプ

       END

【先頭に戻る】


311−2.PIOテストプログラムpiotes1B.asmの説明

基本的にはPIC16F84A用のプログラムと一緒ですが、以下の点で違いがあります。

 

■list文のプロセッサ指定変更

          list p=16F873

これは大体予想できる変更点です。PIC16F84Aの時には「16F84A」と書いてあった部分を「16F873」に書き換えて、プロセッサを指定し直しています。

 

■インクルードファイルの指定変更

         #include <p16F873.inc>

これも予想できますね。PIC16F873用のレジスタ設定のされたインクルードファイルに指定し直します。ただし、MPLABがインストールされているフォルダに、このファイルがあることを確認しておく必要はあります。

 

■コンフィグレーションビットの設定追加

          __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC & _LVP_OFF

これはちょっと予想できませんでした。コンフィグレーションビットの設定に、「_LVP_OFF」という設定を追加しています。

ところで、PIC16F873のコンフィグレーションビットには、以下の項目があります。その中で、ビット名の部分を黄色で表示しているビットが、16F84Aにはなかったものです。

PIC16F873のコンフィグレーションビット

ビット名 選択肢 説 明
FOSC RC/HS/XT/LP PICに使用している発振回路を指定する。
WDTE ENABLE/DISABLE ウォッチドックタイマを利用するかしないかを指定する。
PWRTE DISABLE/ENABLE 電源投入直後の72mS期間のリセット動作をするかしないかを指定する。
BODEN ENABLE/DISABLE ブラウンアウトリセット(電源電圧低下によるリセット)をするかしないかを設定する。
LVP RB3:PGM/RB3:GPIO 低電圧(5V)プログラミングの有効/無効を設定する。有効だとRB3端子はプログラミング専用になる。
CPD DISABLE/ENABLE 内部EEPROMデータメモリのコードプロテクトをするかしないかを設定する。
WRT ENABLE/DISABLE ユーザープログラムがEECONレジスタを使用してFLASHプログラムメモリへの書き込みをするかしないかを設定する。
DEBUG DISABLE/ENABLE インサーキットデバッグモードの有効/無効を設定する。有効だとRB6,RB7端子はデバッグ専用になる。
CP DISABLE/0800H-0FFFH/0F00H-0FFFH/ALL コードプロテクトをするかしないかを指定する。

今回は、& _LVP_OFF というのを追加しました。これは、RB3ビット(PORTBの3ビット目)を低電圧プロブラミング用の特殊用途として使用せず、PIOの汎用端子として使用するという設定です。このLVP設定ビットは、初期設定で特殊用途に割り当てられてしまうため、ここで設定を変更しています。

この設定を行なわないと、PORTB3ビット目は常にの状態となります。つまり、3ビット目のLEDは常に点灯状態になり、プログラム上からの制御が行なえません。汎用PIOとして利用する場合には、必ず & _LVP_OFF を追記してください。

その他のコンフィグレーションビットは、わざわざ設定を追記していません。それは、初期状態のままで正常に動作するためです。ただし本当は明示的に設定を行なうべきかもしれません。ただ手抜きをしただけとも言えます...

 

■A/Dコンバータ用レジスタの設定追加

          MOVLW   06H               ;Wレジスタに06Hをセット
          MOVWF   ADCON1         ;ADCON1に06Hをセット PORTA全てデジタル

ん?? 今回のプログラムはスイッチ入力をLED表示させるだけで、A/D変換なんて使ってないのに、何でそんなことするの???

と怒られそうですが、どうしてもこれが必要なのです。

A/D変換機能の設定を行なうレジスタにはADCON0ADCON1の2種類があります。

ADCON0は変換クロックの選択やアナログ入力チャンネルの選択、あとはA/D変換動作の状態を取得するなど、実際のA/D変換時に活躍するレジスタです。

そして、ADCON1はアナログ入力が可能な端子を、本当にアナログ入力として使うのか、デジタル入出力用として使うのかを設定します。また、アナログの基準電圧をどこから取得するかといった設定も行ないます。今回の設定に必要なのは、このADCON1のほうです。

ADCON1には、以下の機能があります。

7 6 5 4 3 2 1 0
ADFM - - - PCFG3 PDFG2 PCFG1 PCFG0

ADFMビットについては、実際のA/D変換機能をご紹介するときに説明します。ここではPCFG0〜3ビットが端子の用途を決定する要因となり、以下のようにして決まることを見て下さい。

PCFG3,2,1,0 AN4/RA5 AN3/RA3 AN2/RA2 AN1/RA1 AN0/RA0 Vref+ Vref-
0 0 0 0 A A A A A VDD VSS
0 0 0 1 A Vref+ A A A RA3 VSS
0 0 1 0 A A A A A VDD VSS
0 0 1 1 A Vref+ A A A RA3 VSS
0 1 0 0 D A D A A VDD VSS
0 1 0 1 D Vref+ D A A RA3 VSS
0 1 1 x D D D D D VDD VSS
1 0 0 0 A Vref+ Vref- A A RA3 RA2
1 0 0 1 A A A A A VDD VSS
1 0 1 0 A Vref+ A A A RA3 VSS
1 0 1 1 A Vref+ Vref- A A RA3 RA2
1 1 0 0 A Vref+ Vref- A A RA3 RA2
1 1 0 1 D Vref+ Vref- A A RA3 RA2
1 1 1 0 D D D D A VDD VSS
1 1 1 1 D Vref+ Vref- D A RA3 RA2

 A:アナログ入力端子として機能する。

 D:デジタル入出力端子として機能する。

 Vref+:A/D変換のとき、アナログの基準電圧のプラス端子として機能する。 

 Vref-:A/D変換のとき、アナログの基準電圧のマイナス端子として機能する。

 VDD:PICのプラス側電源端子

 VSS:PICのマイナス側電源端子(GND)

ここで何もしないと、ADCON1レジスタは 0 0 0 0の値をとります。つまり、PORTA0,1,2,3,5の各ビットは、全てアナログ入力用の端子の設定になっています。PICのデータシートには、「アナログ入力として構成されているピンをリードすると、0(Lowレベル)とリードされます」とあります。つまり、アナログ入力に設定されている端子をPIOのつもりでデータを読むと、必ず0(ゼロ)として読まれるということです。これでは正常なデジタルデータの入力は出来ません。

そこで、

          MOVLW   06H 
          MOVWF   ADCON1

によって、ADCON1レジスタに06Hのデータを書き込んでいます。06Hつまり 下位4ビットは0110ですので、上の表の青色の設定によって全てデジタル入出力として使えるということになります。

なんで初期設定でデジタル入出力じゃないの?なんて言わないで下さい。そういうものなのだから仕方ありません。そこがクセということになるのでしょう。

 

■あとは変更点なし。

あとはPIC16F84Aと同じプログラムです。ただし、今回は使用していませんが、データの一時保管場所である汎用レジスタなどを使おうという場合は、その開始アドレスが異なるため注意が必要だったりもします。

【先頭に戻る】


311−3.実験風景

以下が実験風景の写真です。

実験風景写真 左側がPIC16F873を載せた実験基板で、右がテスト用の簡易I/O基板です。

右側の基板の下の方で、LEDが6ビット分点灯しているのが分かりますか?その部分が同じ基板についているディップスイッチの状態で点灯/消灯します。PIC16F84Aの時は5ビット分まででしたが、PIC16F873はPORTAが6ビット分まで対応しているため、こうなります。

 

【先頭に戻る】


今回はPICの機種ごとに持つ機能の違いに起因するクセをつかんで、プログラムを移植する例をご紹介しました。動作がなぜか変で、プログラムをいくら見直しても原因がつかめない!といったことが起きた場合には、コンフィグレーションビットや、関連しそうなレジスタの設定を見直してみて下さい。そこに原因が隠れているかもしれません。

 

【ソフトウエア編TOPに戻る】


【表紙に戻る】