[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);
}
}
}
Comments are currently closed.
