目次8章.機能が豊富なPICを使う(PIC16F88)>(3)A/D変換を使う

A/D変換を使う

更新日2008.2.16

PIC16F88のA/D変換機能を使って見ます。考え方は他のPICでも同じです。

ここで行う内容は、RA3(AN3)でA/D変換し、結果の10ビットを7セグメントLEDに16進数3桁で表示させるというものです。

A/D変換について
A/D変換とは、アナログ信号(電圧)をデジタルデータに変換することです。
PIC16F88では、AN0〜AN6の7つをアナログポートに設定可能で、プログラムによりピン毎にデジタル/アナログどちらかに設定できます。
ピン番号デジタル設定アナログ設定
17RA0AN0
18RA1AN1
1RA2AN2
2RA3AN3
3RA4AN4
12RB6AN5
13RB7AN6
アナログ入力に設定したポートは、入力電圧を10ビットのデジタルデータに変換することができます。
変換は、基準電圧(後述)を1024として測定電圧を表現します。

ADres=Vin/(Vref/1024)

ただし、ADresの最大値は1023です。(16進表現で、'3FF'まで)

例えば、基準電圧が5Vで測定電圧が2.5Vの場合、AD変換の結果(ADres)は512になります。

ADres=Vin/(Vref/1024)
=2.5/(5/1024)
=512
【参考】
基準電圧は、+と−の両方が指定できます。(Vref+/Vref-)
ここでは、−側を0Vとして記載しています。

実験回路
今回の実験回路は以下の通りです。

RA3(AN3)をアナログ入力とし、可変抵抗を接続して電圧を変化できるようにします。
PORTBの8ピンとRA0−2には7セグメントLEDを接続します。
レゾネータ(セラロック)は20MHzを使用しました。

7セグメントLEDの使い方については、こちらを参考にして下さい。

パスコンは省略。

ブレッドボードに組み込んだ状態

プログラムの仕様
RA3(AN3)に接続したボリュームで電圧を変化させ、その電圧をA/D変換してPICに取り込みます。
A/D変換で取り込んだ値を3個の7セグメントLEDに16進数で表示します。

以下では、A/D変換の方法について説明します。

A/D変換の手順

A/D変換を行う手順は以下の通りです。

(1)A/D変換機能の初期設定
以下の5つのレジスタ設定を行います。
TRISA/BA/D変換で使うポートを入力モードに設定
ANSELアナログモードにするポートを指定
ADCON1A/D変換のクロック設定,基準電圧の選択,A/D変換結果の格納方法を設定
ADCON0A/D変換のクロック設定,A/D変換を有効に設定

(2)A/D対象ポートの選択
1回のA/D変換動作で対象とするポートは1ポートですので、今回対象とするポートを選択します。
この選択は、ADCON0レジスタのCHS0〜2で指定します。
アナログ入力が1ポートだけであれば、この処理は初期設定で1回やっておけばOKです。

(3)A/D変換準備完了を待つ
PIC内蔵のA/D変換用コンデンサ充電完了を待ちます。
この時間をアクィジション時間と言い、入力抵抗が10KΩの時、約20μ秒です。

(4)A/D変換を開始する
ADCON0レジスタのGO/^DONEビットをONにしてA/D変換を開始します。

(5)A/D変換完了を待つ
ADCON0レジスタのGO/^DONEビットがOFF(A/D変換完了)になるのを待ちます。

(6)A/D変換結果を使う
A/D変換結果が、ADRESH,ADRESLレジスタに格納されていますので、目的に応じて使用します。

(7)繰り返す
繰り返す場合は、(2)に戻ります。

【参考】
A/D変換完了を待つ方法として、上ではADCON0レジスタのGO/^DONEビットがOFFになるのを待っていますが、A/D変換完了割込みを使う方法もあります。
A/D変換完了割込みを使う場合、以下のレジスタ操作が必要です。
INTCON,PIR1,PIE1

更に別の方法として、A/D変換完了までSLEEP状態で待つ事もできます。



【参考】
GO/^DONEの表記について
データシートでは、GO/___
DONE

と、DONEにオーバー・バーを付けて記載されていますが、ここでは簡易的にキャレット「^」を付けて表記しています。
共に、ビットの否定(論理演算で言うところの)の意味です。


入力ポートの選択

A/D変換で使えるポートは、
RA0(AN0)〜RA4(AN4)
RB6(AN5)〜RB7(AN6)
の7ポートがあります。
どのポートをアナログモードにするかは自由に選択できます。
A/D変換で使わない(アナログモードにしない)ポートはデジタルI/Oで使用できます。
この選択は、ANSELレジスタのANS0〜ANS6で指定します。(AN0〜AN6に対応)
ANSELレジスタ
Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0
-ANS6ANS5ANS4ANS3ANS2ANS1ANS0

1:アナログ入力
0:デジタル入出力

今回は、RA3/AN3のみをアナログポートとして使用しますので、ANS3のみ1にして他は全て0にします。

ただし、1回のA/D変換動作では、1つのポートだけを対象とする必要があり、このポート選択は、ADCON0レジスタのCHS0〜2で設定します。

ADCON0レジスタ
Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0
ADCS1ADCS0CHS2CHS1CHS0GO/^DONE-ADON
CHS(2-0)ANポート
000RA0/AN0
001RA1/AN1
010RA2/AN2
011RA3/AN3
100RA4/AN4
101RB6/AN5
110RB7/AN6

今回は、RA3/AN3のみをアナログポートとして使用しますので、CHS(2-0)にはb'011'をセットします。

基準電圧

基準電圧は、以下のいずれかを組み合わせて選択します。

・電源電圧VddまたはRA3/Vref+
・電源電圧VssまたはRA2/Vref−

これらは、ADCON1レジスタのVCFGビットで設定します。

ADCON1レジスタ
Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0
ADFMADCS2VCFG1VCFG0----

VCFG(1-0)Vref+Vref-
00VddVss
01VddVref-
10Vref+Vss
11Vref+Vref-

今回は、精度は要求されませんので、電源電圧(Vdd,Vss)を基準電圧にしました。

A/D変換のクロック選択(TAD

A/D変換のクロック(TAD)は、下の表の水色の範囲を指定します。(1.6μS以上6.4μS以下)
PICを動作させるオシレータ(クロック)の周波数と、ANCON0/1レジスタのADCS2〜0の設定値で決定します。
今回は、オシレータを20MHzにしましたので、32Toscを選択し1.6μ秒にしました。

A/Dクロック設定オシレータ周波数
動作ADCS2-020MHz5MHz4MHz1.25MHz
2Tosc000100nS400nS500nS1.6μS
4Tosc100200nS800nS1.0μS3.2μS
8Tosc001400nS1.6μS2.0μS6.4μS
16Tosc101800nS3.2μS4.0μS12.8μS
32Tosc0101.6μS6.4μS8.0μS25.6μS
64Tosc1103.2μS12.8μS16.0μS51.2μS
A/D RCx112-6μS2-6μS2-6μS2-6μS
表の水色の範囲になるようADCS2〜0を設定します。
A/D変換のクロック(TAD)は、最低が1.6μSですので、表の青の部分は使用できません。
また、最大は6.4μSですので赤の部分は使用できません。
【ToscとFosc】
Toscはオシレータの1クロック(1サイクル)の時間であり、8Toscは1クロックの時間の8倍という意味です。
Foscはオシレータの周波数で、Fosc/8はオシレータの周波数の1/8という意味です。


【A/D変換にかかる時間】
1回のA/D変換に必要な最低時間は以下の通りです。
(TAD=1.6μSの場合)
アクィジション時間 + A/D切替時間 + A/D変換時間
=20μS + 0.1μS + 1.6μS × 12
=39.3μS


A/D変換結果の格納

A/D変換結果は10ビットです。一方、PICのレジスタは8ビットです。
そのままでは格納できませんので、ADRESHレジスタとADRESLレジスタの2つを連結した16ビットに格納されます。

ADRESHADRESL
Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0
A/D変換結果(10ビット)000000
000000A/D変換結果(10ビット)

上の図の水色部分にA/D変換結果が格納されます。
2列で表しているように、格納方法は2パターンあります。どちらにするかは、ADCON1レジスタのADFMビットで指定します。
 ADFM=0:左詰め(2列の上のパターン)
 ADFM=1:右詰め(2列の下のパターン)

今回は右詰めとしました。

プログラム全体
プログラムはこちらです。
メモ帳などのテキストエディタに取り込んで、MPLABでアセンブル&PICライタでPICに書き込んで動かしてみて下さい。

今まで、PIC16F84Aを使用していた場合は、MPLABのプロジェクトウィザードで「PIC16F88」を選択して下さい。
また、PICライタでも同様に「PIC16F88」を選択して下さい。

ボリュームを回して、7セグメントLEDに「000」〜「3FF」の範囲の値が表示されれば成功です。


この回路を応用した温度計を近いうちにアップする予定です。