analogRead()

概要

analogRead()は、アナログ‐デジタル(AD)変換器を使って、アナログピンから値を読み取ります。

Arduino Unoは、10ビットのAD変換機を6個持っています。analogRead()では、ADMUXとADCSRA、ADCL、ADCHという4つのレジスタを利用します。

ADMUX

ADMUX(ADC Multiplexer Selection Register)は、参照電圧の設定と出力値の形式(ビットを左詰めにするか右詰めにするか)、チャネル(アナログピン)の選択を制御するレジスタです。

ADMUX
ビット76543210
名称REFS1REFS0ADLAR-MUX3MUX2MUX1MUX0

REFS0とREFS1は、参照電圧の設定を行います。組み合わせにより意味が異なります。

REFS1REFS0意味analogReference()の引数
00AREFピンに与えた電圧EXTERNAL(0)
01デフォルトの参照電圧(Arduino Unoの場合は5V)DEFAULT(1)
10予約(未使用)-
11内蔵の参照電圧(Arduino Unoの場合は1.1V)INTERNAL(3)

ADLARは、読み取った値を格納するレジスタ(ADCLとADCH)の値が、左詰め(1)か右詰め(0)かを指定します。Arduinoでは、右詰め(0)固定です。

MUX0からMUX3はアナログピンの選択のためのビットです。4つのレジスタの値の組み合わせによりピンを選択します。Arduino Unoでは、以下の組み合わせが有効です。

MUX3MUX2MUX1MUX0アナログピン
00000
00011
00102
00113
01004
01015
01106

MUX3…MUX0=1000を選択すれば、内蔵温度センサから値を読むことができますが、この機能はanalogRead()では利用できません。詳細は、内蔵温度センサの実験のページをご覧ください。

ADCSRA

ADCSRA(ADC Control and Status Register A)は、AD変換器の制御を行うためのレジスタです。

ADCSRA
ビット76543210
名称ADENADCSADATEADIFADIEADPS2ADPS1ADPS0

ADEN(ADC Enable)を1に設定すると、AD変換を有効にします。AD変換を有効にする処理は、main()関数から呼ばれるinit()という関数の中で行なわれています。

ADSC(ADC Start Conversion)を1にするとAD変換を開始します。AD変換が行われているときはこのビットは1で、AD変換が終了すると0になります。

ADATE(ADC Auto Trigger Enable)は、AD変換の自動起動を制御します。Arduinoでは使われていないようです。

ADIF(ADC Interrupt Flag)とADIE(ADC Interrupt Enable)は、割り込みに関する制御を行います。Arduinoでは使われていないようです。

ADPS(ADC Prescaler Select Bits)2とADPS1、ADPS0は、クロックの分周比を設定するためのビットで、AD変換の際のクロック数を決めます。組み合わせの意味は以下の通りです。

ADPS2ADPS1ADPS0分周比
0002
0012
0104
0118
10016
10132
11064
111128

AD変換で10ビットの精度を得るためには、50kHz~200kHzのクロックを供給する必要があります。精度を落としていいのであれば、200kHzよりも高い周波数でもいいようです。Arduino Unoでは、init()の中で、ADPSを0b111、すなわち、分周比を128に設定しています。Arduinoで使っているクロックの周波数は16MHzなので、結果として、16MHz/128 = 125kHzとなります。また、AD変換には13クロックを要するため、AD変換を行うのに必要な時間は、1/125kHz*13 = 0.000104秒 = 104マイクロ秒となります。

ADCH、ADCL

ADCHとADCLは、AD変換の結果を格納するレジスタです。ADMUXレジスタのADLARビットの値により、結果の格納方法が異なります。Arduinoでは、ADLARビットは0と設定するため、10ビットの変換結果の上位2ビットがADCHに、下位8ビットがADCLに格納されます。

analogRead()のリファレンスはこちらをご覧ください。

ソースコード

analogRead()は、hardware/arduino/avr/cores/arduino/wiring_analog.c に定義されています。以下に全ソースコードを示します。Arduino Unoの場合に適用される部分だけを抜粋しています。実際には#if によりさまざまなチップに対応しています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
int analogRead(uint8_t pin)
{
    if (pin >= 14) pin -= 14; // allow for channel or pin numbers
 
    // set the analog reference (high two bits of ADMUX) and select the
    // channel (low 4 bits).  this also sets ADLAR (left-adjust result)
    // to 0 (the default).
    ADMUX = (analog_reference << 6) | (pin & 0x07);
 
    // without a delay, we seem to read from the wrong channel
    //delay(1);
 
    // start the conversion
    sbi(ADCSRA, ADSC);
 
    // ADSC is cleared when the conversion finishes
    while (bit_is_set(ADCSRA, ADSC));
 
    // ADC macro takes care of reading ADC register.
    // avr-gcc implements the proper reading order: ADCL is read first.
    return ADC;
}

入力はpinで、uint8_t型の変数です。出力はintで、AD変換の結果の10ビットを返します。

まず、pinの番号の変換を行います。

3
    if (pin >= 14) pin -= 14; // allow for channel or pin numbers

例えば、アナログピンの0番は、0という数値かA0という変数で表します。Arduino Unoでは、A0は14、A1は15というように定義されています(hardware/arduino/avr/variants/standard/pins_arduino.h)。このため、最初にpinが14以上の場合はA0などの表記が使われたとみなし、14を引く処理をしていると思われます。A0が14と定義されているのは、アナログピンをデジタルピンとして使うこともでき、アナログピンの0番がデジタルピンの14番として利用できるためです。

次に、ADMUXレジスタを設定します。

8
    ADMUX = (analog_reference << 6) | (pin & 0x07);

analog_referenceはADMUXのREFS1(ビット7)とREFS0(ビット6)に設定されます。pinは、0x07(二進数では0b00000111)と論理積をとり、これらを論理和で連結します。ADLARは明示して設定はしていませんが、0が設定されます。

AD変換を開始します。

13
14
    // start the conversion
    sbi(ADCSRA, ADSC);

sbi()は、第1引数で指定したアドレスの内容の第2引数ビットを1に設定するマクロです。ADCSRAのADSCビットをセットすることでAD変換が開始されます。

AD変換が終了するのを待ちます。

16
17
    // ADSC is cleared when the conversion finishes
    while (bit_is_set(ADCSRA, ADSC));

bit_is_set()は、第1引数の第2引数ビット目が1かどうかを調べるマクロです。ADCSRAのADSCが1の間はループで待ちます。0になればAD変換完了です。

AD変換結果が格納されているADCLとADCHを読み取り、16ビット(上位6ビットは0)の数値に変換して、リターンします。

ADCLを読みだすと、その後ADCHを読みだすまではADCHは更新されません。このため、先にADCLを読む必要があります。

この変換は、ADCマクロで行います。

19
20
21
    // ADC macro takes care of reading ADC register.
    // avr-gcc implements the proper reading order: ADCL is read first.
    return ADC;

バージョン

Arduino AVR Boards 1.8.6

最終更新日

March 21, 2023

inserted by FC2 system