技術を間違った情熱に使いがちな人のページ

[AVRexample] A/D 変換

<<目次へ戻る

ATtiny2313にはAD変換機能がついていない。
ここのサンプルは 8pinDIPの ATtiny13A のもの。
レジスタ名はmegaシリーズと同じなので使い回しはやりやすい。

●基本

PB3の電圧に応じてPB0のLED点滅間隔が変わる。
AVRはAD変換関連のレジスタが入り組んでいる。
良いサンプルも見つからず、動作まで大変だった。
ATtiny13向け。

#include <avr/io.h>
#include <util/delay.h>
// AVRwiki より拝借マクロ
// cbi()    addrのbit番目をLowに
// sbi()    addrのbit番目をHighに
#define cbi(addr,bit)     addr &= ~(1<<bit)
#define sbi(addr,bit)     addr |=  (1<<bit)

int main(void)
{
    uint8_t ad_data;
    int c;
    DDRB = ~0b00111100;
    PORTB = 0b00111100;

    ADCSRA |= _BV(ADEN);                          //A/Dを許可
    ADCSRA |= _BV(ADPS2)|_BV(ADPS1)|_BV(ADPS0);    //ADCクロック128分周
    sbi(ADMUX,ADLAR);                            // 左詰めで格納。10bit中の上位8bit取り出し 
    ADMUX |= _BV(MUX1)|_BV(MUX0);                // AD入力chはADC3(PB3)

    while(1)
    {
        sbi(ADCSRA,ADIF);                        //変換完了フラグをリセット
                                                // 書き込む事でリセットできる。変換前には呼び出す事
        sbi(ADCSRA,ADSC);                       //変換開始。ADSC(A/D変換開始レジスタ)

        loop_until_bit_is_set(ADCSRA,ADIF);      //変換完了フラグが1になるまで待機
        ad_data=ADCH;                           //ad_dataにデータの上位8ビットを格納

        PINB |= _BV(0);                        //PB0を点滅させるためにトグル

        //delay_ms()の内部に直接変数を書くとコンパイルサイズが巨大になる。外ループで作ってやると良い
        for(c=0;c<ad_data;c++)
        {
            _delay_ms(1);
        }
    }
}

 

 

●基本を関数化

単発変換なので一個にまとめてみた。
一回定義すれば良いレジスタをいちいち呼び出して無駄だけど
使いやすいので実用的かな
これもATtiny13向け

#include <avr/io.h>
#include <util/delay.h>
// AVRwiki より拝借マクロ
// cbi()    addrのbit番目をLowに
// sbi()    addrのbit番目をHighに
#define cbi(addr,bit)     addr &= ~(1<<bit)
#define sbi(addr,bit)     addr |=  (1<<bit)

// AD変換用関数。
// 引数 adch はAD変換ポート番号を指定すること。
// PORT番号じゃなくて、AD変換ポートの番号[ADC 0-8]の事。
uint8_t singleADC(uint8_t adch)
{
    ADCSRA |= _BV(ADEN);                          //A/Dを許可
    ADCSRA |= _BV(ADPS2)|_BV(ADPS1)|_BV(ADPS0);    //ADCクロック128分周
    sbi(ADMUX,ADLAR);                            // 左詰めで格納。10bit中の上位8bit取り出し 
    ADMUX |= adch;                                //  adch をAD入力chとする

    sbi(ADCSRA,ADIF);                            //変換完了フラグをリセット
    sbi(ADCSRA,ADSC);                           //変換開始。ADSC(A/D変換開始レジスタ)

    loop_until_bit_is_set(ADCSRA,ADIF);        //変換完了フラグが1になるまで待機
    return ADCH;                               //ad_dataにデータの上位8ビットを格納
}

int main(void)
{
    uint8_t ad_data;
    int c;
    DDRB = ~0b00111100;
    PORTB = 0b00111100;

    while(1)
    {
        ad_data = singleADC(2);    //上記"基本"とは違うポート番号。ATtiny13の場合PB4pinのADC2を指していることになる。

        PINB |= _BV(0);
        for(c=0;c<ad_data;c++)
        {
            _delay_ms(1);
        }
    }
}

Posted in AVR, 電子

Comments are currently closed.