A/D変換モジュールの使い方


【A/D変換モジュール概要】

PIC18シリーズに内蔵のA/Dコンバータは、5または8チャンネルの10ビット
分解能を持つA/D変換モジュールとなっています。このA/D変換モジュール
は基本的にPIC16F8xxシリーズのものと同じです。

【A/D変換モジュールの構成】

A/D変換モジュールの内部構成は下図のようになっていて、動作は下記の
順序で実行されます。

(1) 動作モードを設定する。Vrefの指定、変換クロック速度の指定など。
   (ADCON0、ADCON1レジスタで設定)
(2) 入力チャンネルを選択する。
   (ADCON0レジスタで指定)
(3) サンプルホールドコンデンサの充電が開始される。(一定時間が必要)
     (Acquisition Time)
(4) A/D変換をスタートする。変換動作終了はフラグチェックか割込みで確認
  (ADCON0のGOビットOnでスタート、終了確認はGOビットが0になるのを待つ)
(5) 2バイトのレジスタに変換結果が書き込まれている
  (ADRESL,ADRESHレジスタ)





【A/D変換制御用レジスタ】

A/D変換モジュールを制御するためのレジスタには下記のように ADCON0と
ADCON1の2種類があります。このレジスタの内容は基本的にはPIC16シリーズと
同じなのですが、チャンネル数が増えたのでチャネル指定ビットが増えたのと
クロックの指定も細かくなったのでその指定ビットも増えています。











アナログ入力ポートの使い方の設定は下表のようになります

PCFG3−0

RE2

RE1

RE0

RA5

RA3

RA3

RA1

RA0

0000

A

A

A

A

A

A

A

A

0001

A

A

A

A

Vref+

A

A

A

0010

D

D

D

A

A

A

A

A

0011

D

D

D

A

Vref+

A

A

A

0100

D

D

D

D

A

D

A

A

0101

D

D

D

D

Vref+

D

A

A

011x

D

D

D

D

D

D

D

D

1000

A

A

A

A

Vref+

Vref-

A

A

1001

D

D

A

A

A

A

A

A

1010

D

D

A

A

Vref+

A

A

A

1011

D

D

A

A

Vref+

Vref-

A

A

1100

D

D

D

A

Vref+

Vref-

A

A

1101

D

D

D

D

Vref+

Vref-

A

A

1110

D

D

D

D

D

D

D

A

1111

D

D

D

D

Vref+

Vref-

D

A

 Aはアナログ入力 Dはディジタル入出力 Vref+ Vref-は基準電圧入力
 基準電圧入力の指定が無いときは、電源電圧が基準となる。

【A/D変換の精度】 

10ビット精度のA/D変換モジュールですが、実際に10ビットの精度を出すためには
条件があります。下記条件を守らないと10ビット精度は悪化します。

条件 VrefH − VrefL > 3V

つまりリファレンス電圧差が3V以上無いと精度は保証されません。

【A/D変換用C言語関数】

MPLAB-C18で用意されているA/D変換モジュール用のC言語ライブラリを
説明します。
A/D変換の制御は比較的やさしいのですが、Acquisition Timeを十分確保
しないと精度が出なくなるので要注意です。

(1) ライブラリ関数の種類と機能
  MPLAB-C18にあらかじめ用意されているA/D変換モジュール用の関数は
  下記表となっています。

関数名 機能と基本形 使用例
BusyADC A/D変換中の時1を返す
ADCON0レジスタのGOビットの状態を返す
while(BusyADC( ));
char BusyADC(void);
CloseADC まずADCON0のADONビットをクリアしてA/Dコンバータを
未使用状態にしてから割り込みも禁止する
CloseADC( );
void CloseADC(void);
ConvertADC A/D変換を開始する。(ADCON0のGOビットを1にする) ConvertADC();
void ConvertADC(void);
OpenADC A/D変換機能の使用モードを設定し動作を開始させる。
設定内容は、変換クロック、割込み、データ配置、
基準電圧、チャンネル数、チャネル選択
OpenADC(ADC_FOSC_32 &
 ADC_RIGHT_JUST &
 ADC_1ANA_0REF,
 ADC_CH & ADC_INT_OFF);
void OpenADC(unsigned char config,
         unsigned char config2);
ReadADC A/D変換した結果の符号付2バイトのデータを返す。
右詰、左詰は
OpenADCの設定による
int result;
result = ReadADC( );
int ReadADC(void);
SetChanADC 一度チャンネル0に戻してから指定したチャンネルを選択する。 SetChanADC(ADC_CH0);
void SetChanADC(unsigned char channel);


(2) OpenADC用パラメータ
  OpenADC関数にはA/D変換モジュールの動作モードを設定するための多くのパラメータが
  必要となりますが、これらは下記のようになっています。

設定項目 パラメータ名称 意味内容
クロック選択 ADC_FOSC_2
ADC_FOSC_4
ADC_FOSC_8
ADC_FOSC_16
ADC_FOSC_32
ADC_FOSC_64
ADC_FOSC_RC
Fosc/2
Fosc/4
Fosc/8
Fosc/16
Fosc/32
Fosc/64
内部クロック
結果の詰め方 ADC_RIGHT_JUST
ADC_LEFT_JUST
右詰め
左詰め
使用チャンネル数
とリファレンス
ADC_8ANA_0REF

ADC_7ANA_1REF

ADC_5ANA_0REF
ADC_4ANA_1REF
ADC_3ANA_0REF
ADC_2ANA_1REF
ADC_0ANA_0REF
ADC_6ANA_2REF
ADC_6ANA_0REF
ADC_5ANA_1REF
ADC_4ANA_2REF
ADC_3ANA_2REF
ADC_2ANA_2REF
ADC_1ANA_0REF
ADC_2ANA_0REF
Vref+=Vdd,Vref-=Vss
8チャンネル全部使用
AN3=Vref+ 他全チャン
ネル使用
Vref=vdd Vref-=Vss
AN3=Vref+
Vref+=Vdd、Vref-=Vss
AN3=Vref+
全部ディジタル
AN3=Vref+、AN2=Vref-
Vref+=Vdd、Vref-=Vss
AN3=Vref+、Vref-=Vss
AN3=Vref+、AN2=Vref-
AN3=Vref+、AN2=Vref-
AN3=Vref+、AN2=Vref-
AN0のみ
AN3=Vref+、AN2=Vref-
チャンネル指定 ADC_CH0
ADC_CH1
ADC_CH2
ADC_CH3
ADC_CH4
ADC_CH5
ADC_CH6
ADC_CH7
SetChanADC関数の
パラメータとしても使用する
割込み ADC_INT_ON
ADC_INT_OFF
割込みを使用
割込み使わず


【A/D変換のプログラム例】

実際にA/D変換を使ったプログラム例です。ここでは、PIC18活用製作例の
汎用ボードを使ったテストプログラムです。

2チャンネルのアナログ信号を読み取って、液晶表示器の各行に表示する
動作を一定時間間隔で実行します。

  ★A/D変換モジュールテストプログラム(18test6.c)


《プログラム例》 メインルーチン部分のみは下記となっています。

//****** Main Function
void main(void)
{
  char Message1[8] = "Start!";
  int data;
  char str[7]; //define ASCII

  TRISB = 0;
  OpenXLCD(FOUR_BIT);
  //define mode of A/D
  OpenADC(ADC_FOSC_16 & ADC_RIGHT_JUST & ADC_3ANA_0REF,
       ADC_CH0 & ADC_INT_OFF);

  putsXLCD(Message1);      //Display start message

  while(1)
  {
    SetChanADC(ADC_CH0);   //Select Channel 0
    Delay10TCYx(5);      //20usec delay
    ConvertADC();       //Start A/D
    while(BusyADC());     //Wait end of conversion
    data = ReadADC();     //Get A/D data
    itoa(data,str);      //Convert to ASCII
    while(BusyXLCD());    //Check LCD busy
    WriteCmdXLCD(0x01);   //Clear LCD
    putsXLCD(str);      //Display ASCII data

    SetChanADC(ADC_CH1);   //Select Channel 1
    Delay10TCYx(5);      //20usec delay
    ConvertADC();      //start A/D
    while(BusyADC());    //wait end of conversion
    data = ReadADC();    //get data
    itoa(data,str);     //convert to ASCII
    while(BusyXLCD());   //check LCD busy
    SetDDRamAddr(0x40);   //move to next line
    putsXLCD(str);     //display data
    Delay10KTCYx(200);   //wait about 0.8sec
  }
}




  トップページへ