SNSへはこちら

AVR32マイコンやってみよう(11) - ADC

そろそろシリーズ終盤に差し掛かってきました。なお現時点でこのマイコンの征服は終わっています(自慢)。

さて、今回はあらゆる電子工作で必須の A/D コンバータの回です。特に書くことも少ないので、短く終われると思います。

コンバータの精度

このマイコンでは 8bit 精度と 10bit 精度の2つから選ぶことができます。ADC.MR.LOWRES ビットを立てれば 8bit、そうでなければ 10bit になります。デフォルトで 10bit ということですね。

時間の設定

ADC あるあるですが以下の2つの時間をレジスタで設定する必要があります。

  1. Sample & Hold Time
  2. Start Up Time

それぞれ簡単に説明です。

Sample & Hold Time

いわゆるサンプルホールド回路に関連する時間です。これについてはこのサイトとかを参考にするといいでしょう。これは A/D コンバータの入力段についていて、刻一刻と変化する電圧値を取り込むために用いるものになっています。より詳細に言えばこの回路は、

  • 入力から電圧をキャパシタ C に取り込み
  • C へのチャージが完了した時(と思われる時間経過後)に入力からの取り込みをやめることで電圧を確保
  • 出力段にオペアンプを用いたボルテージフォロワを付けてその電圧を保持しつつ外部に出力する回路

となります。この信号は後段の本体部に接続されていて、そこから変換が完了するということです。

それで、この Sample & Hold Time は取り込み&電圧保持を行う時間合計を表しています。

Start Up Time

これは ADC ペリフェラルがアイドル時から立ち上がる際に待つべき最小時間を表します。

以上の時間についてはデータシートの Electriacl Characteristics をご覧ください。僕は適当な値で設定します(適当)。だってこれでこれまで困ったことないですし。

あと、精度(Resolution)によって上限 ADC クロック周波数が決まっているので注意してください。

コード

さて、コードです。10bit 精度で構成しました。あと、ADVREF に 3.3V を入れるのをお忘れなく。

#include <avr32/io.h>
#include <stdint.h>

void adc_init(void) {
    AVR32_PM.pbamask |= 1 << 4;

    // Setting for AD0, GPIO3(#9)
    AVR32_GPIO.port[0].gperc = 1 << 3;
    AVR32_ADC.CHER.ch0 = 1;

    AVR32_ADC.MR.prescal = 5; // 5MHz
    AVR32_ADC.MR.shtim = 0xF; // tekitou
    AVR32_ADC.MR.startup = 0x7F; // tekitou
    AVR32_ADC.MR.lowres = 0; // 10bit resolution
}

uint16_t get_adc(int ch) {
    AVR32_ADC.CR.start = 1; //start conversion
    while( !(AVR32_ADC.sr & (1 << ch)) );
    return (&AVR32_ADC.CDR0 + ch)->data;
}

いやーしかし、時間についてはちゃんと決めたほうがいいですね。マジで。いつになるかわかりませんが、今度からちゃんと検討しようと思います。

次回はこの前掲載した UART 以外のシリアル通信のコードを掲載したいと思います。