ADコンバーター / 自動トリガリングモード

参考: 組込み開発のための実践的プログラミング, pp.125-128

自動トリガリングモードはThe AVR Microcontroller and Embedded Systems Using Assembly and C: Using Arduino Uno and Atmel Studioでは取り上げていない。フリーランニングモードのみ、ADCペリフェラル / free runningモードを試す / AD変換値をシリアル通信でPCへ送る -で試した。自動トリガリングモードを使うと、サンプリングレートが細かく制御できる。

トリガーソースは下表のように複数のなかから選べる。ここではタイマー1コンペアマッチBをトリガーソースにしてAD変換をしてみる。トリガーソースのrising edgeでAD変換が開始される。下のコードは割り込みをかけて自動的にTIFR1レジスタOCF1Bフラグをクリアしているが、参考文献のコードのように手動でクリアするのでもよい。

f:id:ti-nspire:20200629150544p:plain:w500

f:id:ti-nspire:20200708025258p:plain:h250

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

void initADC(){
    // 基準電圧はAVCC。
    ADMUX |= (1 << REFS0);

    // クロックを64分周して供給、変換完了割り込み、自動トリガリングモード、ADCをオン。
    ADCSRA |= 0b110 | (1 << ADIE) | (1 << ADATE) | (1 << ADEN);

    // タイマー1コンペアマッチBをトリガーソースに指定。
    ADCSRB |= (1 << ADTS2) | (1 << ADTS0);
}
void initTimer1(){
    // CTCモード、クロックを256分周してカウント(31.25 kHz)。
    TCCR1B |= (1 << WGM12) | (1 << CS12);

    // コンペア値(OCR1Aに指定する)。ここではサンプリング周期を0.5秒にする。15624 = (31.25 kHz * 0.5秒) - 1
    OCR1A = 15624;

    // タイマー1コンペアマッチBフラグのクリアを自動化するため、割り込みを有効化する。
    // フラグをクリアするためだけなのでISR()は記述しない。
    TIMSK1 |= (1 << OCIE1B);
}
ISR(ADC_vect){    // AD変換が完了したら
    PORTD = ADCL; // AD変換値を読み出す。
    PORTB = ADCH;
}

int main(){
    DDRB = 0xFF;
    DDRD = 0xFF;

    initADC();
    initTimer1();

    sei();

    ADCSRA |= (1 << ADSC); // リセット直後も変換する。しなくてもよい。
    while(1);
    return 0;
}