ADCの使い方

 電圧などのアナログ値をデジタル値(数値)に変換する装置(ハードウエア)をA/D変換器(Analog to Digital Converter)という。
例えば、図の様なアナログの信号(電圧値)があった時に①の点では、2Vであったとすると、AD変換器(以下、ADC)を使えば、この電圧値を数値に変換する事が出来る。
          
 ADCでアナログ電圧を数値に変換する事を、サンプリングと言う。サンプリングの周期は、アナログ電圧の周波数に対して、十分短い事が要求される。具体 的には、アナログ電圧の最大の周波数成分に対して2倍以上の速度でサンプルすれば良い事が知られている。(サンプリング定理)
 ただし、実用上は3倍以上、出来れば10倍程度の速度でサンプルすることが望ましい。

 

変換結果とアナログ電圧の関係

 アナログ入力電圧は、ADCによって数値に変換される。この時、数値と実際の電圧との関係は、以下のようになる。

                

 ADCの分解能は10bit(0~1023の数値を表現できる)なので、基準電圧を2.56Vとすると、この間を1024等分する事になる。つまり、

式:変換後の数値と入力電圧・基準電圧の関係

変換後の数値(ADCH、ADCL) = (入力電圧[V](ADC0~ADC12ピン) × 1023) / 2.56(基準電圧:VREF) 

  ということになる。

【注意】
 ここで入力電圧の上限を5Vとしているが、正確には電源電圧が上限となる。従って、電池(3V)などでマイコンを動作させた場合は、3Vが上限になる事に注意。 (USB給電を行った場合は、5V)
 上限を超える電圧を加えると、マイコンが破壊する。

 



AVRマイコン(ATMega32U4)に実装されているADCの主な仕様は、以下の通り

  1. 分解能10-bit
  2. 変換時間 13μs - 260μs
  3. アナログ入力12チャンネル(同時使用は1チャンネル)
  4. 入力可能電圧は 0 - VCC(USB使用の場合は+5V)
  5. 1.1Vの基準電圧源を内蔵 (2.56V ?)
  6. 連続変換、単発変換の切り替え
  7. 割り込みに対応

などである。


プログラミングの手順

設定内容は以下の通り、

  1. AD変換器(以降、ADC)のON/OFF切り替え(ADCSRAレジスタ:ADENビット(第7ビット))
     ADENビットを1にすることで、ADCを起動する。
     
    ADCSRA |= _BV(ADEN);  // AD変換器を起動
  1. AD変換の起動設定(ADCSRA:ADATEビット(第5ビット)、ADCSRB:ADSTxビット(第0から第3ビット))
    AD変換をスタート(トリガともいう)させるイベントを選択する。例えばタイマなどの比較一致などが選択できる。
    ADATEビットを1にセットすると、ADCSRBレジスタのADTS3からADTS0ビットの設定が有効になる。それぞれ、以下のように機能が割り当てられている。

    表:トリガモード一覧
    ADCSRBレジスタ:bitの位置
    (ビットの名前)
    3
    (ADTS3)
    2
    (ADTS2)
    1
    (ADTS1)
    0
    (ADTS0)
    連続変換 0 0 0 0
    アナログ比較器 0 0 0 1
    外部割込み(IRQ0) 0 0 1 0
    タイマ0 比較・一致 0 0 1 1
    タイマ0 オーフロー(TCNT0) 0 1 0 0
    タイマ1 比較・一致 (OCR1B) 0 1 0 1
    タイマ1 オーバフロー(TCNT1) 0 1 1 0
    タイマ1 キャプチャイベント 0 1 1 1
    タイマ4 オーバフロー 1 0 0 0
    タイマ4 比較・一致 (OCR4A) 1 0 0 1
    タイマ4 比較・一致 (OCR4B) 1 0 1 0
    タイマ4 比較・一致 (OCR4D) 1 0 1 1

連続変換(AD変換を1回だけでなく、連続してどんどん行わせる)の設定にしたいなら、以下の様にする。

ADCSRA |= _BV(ADATE);  // ADATEビットを1に設定
ADCSRB &= 0b11110000; // ADTS3~0ビットを0に設定

ADATEビットを0にして、ADSCビット(ADCSRA)を1にすると、AD変換は1回だけ行われる。

ADCSRA &= ~_BV(ADATE); // ADCSRAレジスタは初期値が0なので、通常はこの設定は不要

 

  1. 割り込み設定(ADCSRA:ADIFビット(第4ビット)、ADIEビット(第3ビット))

      AD変換終了時の割り込みを使うかどうかを選択する。ADIFビットは、割り込みが有効であるか否かにかかわらず、変換が終了した場合に1がセットされる。この状態でADIEビットに1が設定されていれば、割り込みハンドラが呼び出される。ADIFビットは、必要に応じてプログラムでクリアする必要がある。(1を書き込むと、クリア(=0)される)
     

    ADCSRA |= _BV(ADIE);  // AD割り込みを許可
    ADCSRA &= ~_BV(ADIE);  // AD割り込みを禁止

    // 割り込みを使わないで、変換終了をチェックする
    if (ADCSRA & _BV(ADIF)) {
        ADCSRA |= _BV(ADIF);   // ADIFフラグをクリアする
        // AD変換終了
    } else {
        // AD変換実行中
    }

  2. 変換時間設定(ADCSRA:ADPS2~0ビット(第0~第2ビット))

      AD変換器の変換時間を設定する。AD変換のクロックは50~200KHzの間で設定できる。(1変換につき13クロックが必要となる)
    ※ADCSRレジスタのビット配置を参照

    システムクロックが16MHzで、変換速度を104uS(104マイクロ秒)としたいなら、以下の様にする。
     
    ADCSRA |= _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0);  // ADPS2~0ビットが111

    これで、何故、104uSなのかというと、
     ○16MHz = 16000000 Hzで、これを1/128するので、125000Hz。
     ○1クロック当たりの時間は1/125000なので、0.000008秒(=8マイクロ秒)
     ○1回の変換に13クロック必要なので、0.000008 × 13 = 0.000104秒 (=104マイクロ秒)

    つまり、1/0.000104=9615.38... で、1秒間で9515.4回(9.5kSPS)、アナログデータを数値に変換する事が出来る。

    「こんなんじゃ、全然速度が足らん」、というあなた! 変換精度を犠牲に出来るのなら、変換速度を上げることもできます。(77kSPS/8bit位が上限?)
     
  3. 変換結果の出力方法(ADMUXレジスタ:ADLARビット(第5ビット))

      変換結果はADCレジスタ(16ビット)に記録されるが、AD変換器の分解能は10ビットなので、長さが合わない。このため、変換結果を上位側に詰めるか、下位側にするかを選択する。具体的には以下の通り。

    表:AD変換結果のレイアウト(ADCレジスタ上のデータの場所)
    ADLAR=1
    15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
    ADC9 ADC8 ADC7 ADC6 ADC5 ADC4 ADC3 ADC2 ADC1 ADC0    -       -       -       -       -       -   
    ADLAR=0
    15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
       -       -       -       -       -       -    ADC9 ADC8 ADC7 ADC6 ADC5 ADC4 ADC3 ADC2 ADC1 ADC0

      実際のアクセスでは、ADCレジスタは8ビットずつ分割して2回に分けて(下位、上位の順)アクセスする。
    上位側のレジスタはADCH、下位側のレジスタはADCLであり、ADLARの設定で、以上の様にデータが設定されることに注意する事。
     
  4. 基準電圧の設定(ADMUXレジスタ:REFS1,0ビット(第7,6ビット))

    AD変換の変換値の基準となる電圧を指定する。変換値への影響については、上の計算式(式:変換後の数値と入力電圧・基準電圧の関係)を参照のこと

    表:基準電圧減の選択
    ADMUXレジスタ:bitの位置
    (ビットの名前)
    7
    (REFS1)
    6
    (REFS0)
    AREFピン(ボード上はVREFピン)を基準電圧とする。 0
    AVCC(Davinci32Uは5V)を基準電圧とする。 0 1
    予約 1 0
    内部2.56V基準電圧 1 1

 

  1. 入力チャンネルの選択(ADMUXレジスタ:MUX4~0ビット(第4~第0ビット)、
    ADCSRBレジスタ:MUX5ビット(第5ビット))

    ATMega32U4には12本のアナログ入力がある。これをどのように切り替えて使うかを選択する。

    表:アナログ入力チャンネルの選択
    ビット
    MUX5~MUX0
    シングルエンド入力ピン 差動入力
    (プラス側)ピン
    差動入力
    (マイナス側)ピン
    倍率
    00 0000 ADC0 N/A
    00 0001 ADC1
    00 0010 N/A
    00 0011
    00 0100 ADC4
    00 0101 ADC5
    00 0110 ADC6
    00 0111 ADC7
    00 1000 N/A N/A N/A N/A
    00 1001 ADC1 ADC0 10x
    00 1010 N/A N/A N/A
    00 1011 ADC1 ADC0 200x
    00 1100 N/A
    00 1101
    00 1110
    00 1111
    01 0000 ADC0 ADC1 1x
    01 0001 N/A
    01 0010
    01 0011
    01 0100 ADC4 ADC1 1x
    01 0101 ADC5 ADC1 1x
    01 0110 ADC6 ADC1 1x
    01 0111 ADC7 ADC1 1x
    01 1000 N/A
    01 1001
    01 1010
    01 1011
    01 1100
    01 1101
    01 1110 1.1V (VBAND GAP)
    01 1111 0V (GND)
    10 0000 ADC8
    10 0001 ADC9
    10 0010 ADC10
    10 0011 ADC11
    10 0100 ADC12
    10 0101 ADC13
    10 0110 N/A ADC1 ADC0 40x
    10 0111 Temperature Sensor      
    10 1000 N/A ADC0 ADC0 10x
    10 1001 ADC5 ADC0 10x
    10 1010 ADC6 ADC0 10x
    10 1011 ADC7 ADC0 10x
    10 1100 ADC4 ADC1 10x
    10 1101 ADC5 ADC1 10x
    10 1110 ADC6 ADC1 10x
    10 1111 ADC7 ADC1 10x
    11 0000 ADC4 ADC0 40x
    11 0001 ADC5 ADC0 40x
    11 0010 ADC6 ADC0 40x
    11 0011 ADC7 ADC0 40x
    11 0100 ADC4 ADC1 40x
    11 0101 ADC5 ADC1 40x
    11 0110 ADC6 ADC1 40x
    11 0111 ADC7 ADC1 40x
    11 1000 ADC4 ADC0 200x
    11 1001 ADC5 ADC0 200x
    11 1010 ADC6 ADC0 200x
    11 1011 ADC7 ADC0 200x
    11 1100 ADC4 ADC1 200x
    11 1101 ADC5 ADC1 200x
    11 1110 ADC6 ADC1 200x
    11 1111 ADC7 ADC1 200x

    また、アナログ入力にはシングルエンド伝送と差動伝送がある。
     
    • シングルエンド伝送とは、1本の信号線でGNDとの電圧の差で信号を伝達する方法
    • 差動伝送とは、2本の信号線を使って両方の信号線の電圧の差を使って信号を伝達する方法 

      いずれの方法も一長一短があるが、より高速に長距離の信号伝送を行いたい場合はノイズに強い差動伝送が使われる。
       
  2. AD変換スタート(ADCSRA:ADSTビット(第6ビット))
    ADSTビットを1にするとAD変換をスタートする。連続変換中にAD変換を停止させたい場合は、0にする。
     

各レジスタのビットの配置は、以下の通り。

ADCSRAレジスタのビット配置

bitの位置
(ビットの名前)
7
(ADEN)
6
(ADSC)
5
(ADATE)
4
(ADIF)
3
(ADIE)
2
(ADPS2)
1
(ADPS1)
0
(ADPS0)
機能
                      
ADEN=1
ADCを起動               
ADEN=0
ADCを停止
ADSC=1
AD変換スタート
                        ADSC=0
AD変換停止
「2.AD変換の
起動設定」を参照
AD変換終了
割り込みフラグ

(「3.割り込み設定」を参照)

ADIE=1
AD変換終了割り
込みを有効

ADIE=0
AD変換終了割り
込みを無効

(「3.割り込み設定」を参照)

システムクロック
の分周比
000 = 1/2
001 = 1/2
010 = 1/4
011 = 1/8
100 = 1/16
101 = 1/32
110 = 1/64
111 = 1/128

初期値 0 0 0 0 0 0 0 0


ADCSRBレジスタのビット配置

bitの位置
(ビットの名称)
7
(ADHSM)
6
(ACME)
5
(MUX5)
4
3
(ADTS3)
2
(ADTS2)
1
(ADTS1)
0
(ADTS0S0)
機能     高速変換モード   「表:アナログ入力チャンネルの選択」を参照 「表:トリガモード一覧」を参照
初期値 0 0 0 0 0 0 0 0


ADMUXレジスタのビット配置

bitの位置
(ビットの名前)
7
(REFS1)
6
(REFS0)

5
(ADLAR)

4
(MUX4)
3
(MUX3)
2
(MUX2)
1
(MUX1)
0
(MUX0)
機能 「表:基準電圧減の選択」参照 「表:AD変換結果のレイアウト」参照 「表:アナログ入力チャンネルの選択」参照
初期値 0 0 0 0 0 0 0 0


DIDR1レジスタのビット配置

bitの位置
(ビットの名称)
7
(ADC7D)
6
(ADC6D)
5
(ADC5D)
4
(ADC4D)
3
2
1
(ADC1D)
0
(ADC0D)
機能  MUX5~0で選択したピンについて、当該ビットを1にセットすると、デジタル入力機能がOFFとなり、
消費電力を削減できる。
初期値 0 0 0 0 0 0 0 0


DIDR0レジスタのビット配置

bitの位置
(ビットの名称)
7
6
5
(ADC13D)
4
(ADC12D)
3
(ADC11D)
2
(ADC10D)
1
(ADC9D)
0
(ADC8D)
機能  MUX5~0で選択したピンについて、当該ビットを1にセットすると、デジタル入力機能がOFFとなり、
消費電力を削減できる。
初期値 0 0 0 0 0 0 0 0


AD変換の入力ピン配置

 前述の通り、ATMega32U4マイコンには12本のアナログ入力がある。それぞれの入力と、基板上のピンの対応は、以下の通り。


サンプルプログラム

 以下の様に、スライドボリュームをADC0に接続し、ボリュームのつまみの位置によってLED(PC7)が点滅するプログラム例を、以下に示す。

 スライドボリュームの出力は、0~5Vの間で変化するためADC0の入力電圧も、同様に変化する。この時のAD変換後の数値は、0~1023となる。


○単発変換によるサンプル

/*
 *  ADの単発変換のサンプルプログラム
 */
#define F_CPU 16000000UL  // 16MHz動作 _delay_ms()などに関係

#include < avr/io.h >
#include < util/delay.h >
#include < avr/interrupt.h >

int main()
{
    unsigned int t;

    CLKPR = 0x80; CLKPR = 0; // 16MHz動作のための設定
 
   DDRC = 0b10000000;         // デバッグ用のLED(PC7)の設定

// ADCの初期化
    ADMUX |=  _BV(REFS0); // 電源5Vを使用、ADC0を使用, データ右詰め
    ADCSRA |= _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0);
                                      // ADEN, ADSC, CK/128
    ADCSRA |= _BV(ADSC);     // ADをスタート

    while(1) {
        if (ADCSRA & _BV(ADIF)) {    // AD変換の終了を確認
            ADCSRA |= _BV(ADIF);
            t = ADC;    // ADCは16bit幅で、8bitずつ2回に分けてアクセスされるので、
                        // 変数アクセス中に割り込みが発生しないように注意すること
            if (t>512) {
                PORTC = 0b10000000;
            } else {
                PORTC = 0b00000000;
            }
            ADCSRA |= _BV(ADSC);     // ADを再スタート
        }
    }
}


○連続変換によるサンプル

/*
 *  ADの連続変換のサンプルプログラム
 *
#define F_CPU 16000000UL  // 16MHz動作 _delay_ms()などに関係

#include < avr/io.h >
#include < util/delay.h >
#include < avr/interrupt.h >

int main()
{
    unsigned int t;

    CLKPR = 0x80; CLKPR = 0; // 16MHz動作のための設定

    DDRC = 0b10000000;         // デバッグ用のLED(PC7)の設定

// ADCの初期化
    ADMUX |= _BV(REFS0); // 電源5Vを使用、ADC0を使用, データ右詰め
    ADCSRA |= _BV(ADEN) | _BV(ADPS2) | _BV(ADATE)| _BV(ADPS1) | _BV(ADPS0);
                                      // ADEN, ADSC, CK/128
    ADCSRB &= 0b11110000;             // ADTS3~0を0で連続変換
    ADCSRA |= _BV(ADSC);     // ADをスタート

    while(1) {
        if (ADCSRA & _BV(ADIF)) {    // AD変換の終了を確認
            t = ADC;    // ADCは16bit幅で、8bitずつ2回に分けてアクセスされるので、
                        // 変数アクセス中に割り込みが発生しないように注意すること
            if (t>512) {
                PORTC = 0b10000000;
            } else {
                PORTC = 0b00000000;
            }
        }
    }
}

 



AD変換と割り込み
 

/*
 *  AD割り込みのサンプルプログラム
 */
#define F_CPU 16000000UL  // 16MHz動作 _delay_ms()などに関係

#include < avr/io.h >
#include < util/delay.h >
#include < avr/interrupt.h >

// 割り込みハンドラ
ISR(ADC_vect)
{
    unsigned int t;

    t = ADC;    // ADCは16bit幅で、8bitずつ2回に分けてアクセスされるので、
                        // 変数アクセス中に割り込みが発生しないように注意すること
    if (t>512) {
        PORTC = 0b10000000;
    } else {
        PORTC = 0b00000000;
    }
}

int main()
{
    CLKPR = 0x80; CLKPR = 0; // 16MHz動作のための設定

    DDRC = 0b10000000;         // デバッグ用のLED(PC7)の設定

// ADCの初期化
    ADMUX |= _BV(REFS0); // Vcc(5V)を基準、ADC0を使用, データ右詰め
    ADCSRA |= _BV(ADEN) |_BV(ADIE)| _BV(ADATE) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0);
                                      // ADEN, ADIE, ADATE, CK/128
    ADCSRB &= 0b11110000;        // 連続変換
    ADCSRA |= _BV(ADSC);         // ADをスタート

    sei(); // 全ての割り込みを許可

    while(1) {
    }
}


 

最終更新:2015年07月16日 15:05