日々の記録

ほどよく書いてきます。

ATTiny13AのADC機能を使う

2013年07月29日 15時31分15秒 | その他雑記
ATTiny13Aという8ピンマイコンを使ってみる。

ADコンバータがちゃんと使えるかの確認。
最終的には8bit程度の分解能で十分なので、左詰で上位8ビットの読み出ししかしませんが、
10bit ADCに変更するのも十分可能でしょう。

ArduinoっぽくAnalogReadという関数にしてみた。


/*
* _20130729_ATTiny13A_ADC.c
*
* Created: 2013/07/29 13:48:05
* Author: makoto
 
ATTiny13A Pin割り振り
1:PB5 RESET ADC0 →出力端子に設定しちゃうとリセット出来なくなるので使わない
2:PB3 CLKI ADC3
3:PB4 ADC2
4:GND
5:PB0 MOSI OC0A
6:PB1 MISO OC0B
7:PB2 SCK ADC1
8:VCC
 
*/

#include <avr/io.h>
unsigned char AnalogRead8bit(unsigned char Ch)
{
//8bit分解能で十分なのを前提に設定を行っている。
 
//デジタル入出力からの切り離し
DIDR0
= (0<<ADC0D) //ADC0ピンの切り離し。しかし、ADC0はリセット端子になってるから設定しちゃダメ
| (0<<ADC1D) //同ADC1
| (1<<ADC2D) //同・・
| (0<<ADC3D); //同・・
 
ADMUX
= (0<<REFS0) //Reference: 0でVCC参照, 1で1.1V内部電圧源
| (1<<ADLAR) //ADC Left Adjust Result: 1にセットすると左詰で結果を出してくる
| (Ch); //ADMUX1, ADMUX0で入力チャンネルを選べる 00から11までADC0からADC3まで対応
 
ADCSRA
= (1<<ADEN) //ADC enable
| (1<<ADSC) //ADC Start Conversion 1にすると変換開始
| (0<<ADATE) //ADC Auto Trigger Enable (for Continuous Conversion)
| (0<<ADIF) //ADC Interrupt Flag 変換完了すると1になるらしい
| (0<<ADIE) //ADC Interrupt Enable 変換完了したときに割り込み許可
| (0b100); //Clock Division: ADコンバータはクロック50-200kHzで性能がよい
//分周は0のとき2、それ以上の時2^n分周 1.2MHz(Default)のとき16分周(100)で75kHz。9.6MHzのとき128分周(111)で75kHz
 
loop_until_bit_is_set(ADCSRA,ADIF); //ADIFビットが1になるまでムダループ
return ADCH;
}
 
unsigned int AnalogRead(unsigned char Ch)
{
//10bit分解能用ルーチン
 
//デジタル入出力からの切り離し
DIDR0
= (0<<ADC0D) //ADC0ピンの切り離し。しかし、ADC0はリセット端子になってるから設定しちゃダメ
| (0<<ADC1D) //同ADC1
| (1<<ADC2D) //同・・
| (0<<ADC3D); //同・・
 
ADMUX
= (0<<REFS0) //Reference: 0でVCC参照, 1で1.1V内部電圧源
| (0<<ADLAR) //ADC Left Adjust Result: 1にセットすると左詰で結果を出してくる
| (Ch); //ADMUX1, ADMUX0で入力チャンネルを選べる 00から11までADC0からADC3まで対応
 
ADCSRA
= (1<<ADEN) //ADC enable
| (1<<ADSC) //ADC Start Conversion 1にすると変換開始
| (0<<ADATE) //ADC Auto Trigger Enable (for Continuous Conversion)
| (0<<ADIF) //ADC Interrupt Flag 変換完了すると1になるらしい
| (0<<ADIE) //ADC Interrupt Enable 変換完了したときに割り込み許可
| (0b100); //Clock Division: ADコンバータはクロック50-200kHzで性能がよい
//分周は0のとき2、それ以上の時2^n分周 1.2MHz(Default)のとき16分周(100)で75kHz。9.6MHzのとき128分周(111)で75kHz
 
loop_until_bit_is_set(ADCSRA,ADIF); //ADIFビットが1になるまでムダループ
return ADC;
}
int main(void)
{
//PB4(ADC2)からアナログ値を読み込み、PB0からPB3に4ビット表示。
DDRB = 0b1111; //出力端子設定
while(1)
{
PORTB = AnalogRead8bit(2) >> 4; //アナログ値読み込みとビットシフト
}
}
 




Atmel Studio 6.1を使っています。

以上のコードをコンパイルすると74バイト。コードの割にはでかくね?
コメント (4)   この記事についてブログを書く
« 鉛電池のパルス充電器 | トップ | パルス充電器(端子開放検出... »

4 コメント

コメント日が  古い順  |   新しい順
Pic Basic の場合 (いち)
2013-07-30 04:32:46
やほやほ。頑張ってますね。(^^)

私が使っている PIC Basic の場合、A/D入力はめちゃ簡単で、
  ADCIN  入力Ch, 結果を代入する変数
と書くだけで使えます。

ちなみに、以前に送った、8PINのPICで作った放射線センサーのメインプログラムです。
 ・AD値がノイズレベル以上なら、
 ・ピーク値を検出
 ・ピークホールド回路をリセット
 ・シリアル出力
という動作ですが、プログラムには1時間もかかりませんでした。(^^;)

'***** Main Routin *****

thlv = 50

DO
'A/D入力 スレッショルド以上か
repeat
adcin 0,ad
until ad => thlv

'ピーク値検出
repeat
ad0 = ad
adcin 0,ad
until ad <= ad0

'ピークホールドリセット
pres = 1 'Peek Reset
pauseus 5
pres = 0 'Peek Hold Mode

'シリアル出力
hserout [dec4 ad0,lf] '5 Byte

LOOP '無限ループ

(I/O設定、変数定義などは省略)
文字化け (いち)
2013-07-30 04:43:14
あれ、TABが美味く表示されてなかったですね。(^^;)

'***** Main Routin *****

thlv = 50 'ノイズレベル

DO

'A/D入力 スレッショルド以上か
repeat
adcin 0,ad
until ad => thlv

'ピーク値検出
repeat
ad0 = ad
adcin 0,ad
until ad <= ad0

'ピークホールドリセット
pres = 1 'Peek Reset
pauseus 5
pres = 0 'Hold Free

'シリアル出力
hserout [dec4 ad0,lf] '5 Byte out

LOOP '無限ループ

(I/O設定、変数定義などは省略)
ほへぇ (いち)
2013-07-30 04:49:49
あれれ? スペースで書いてもだめ?
とりあえず、続きの不足分をば。

'ピークホールドリセット
pres = 1 'Peek Reset
pauseus 5
pres = 0 'Hold Free

'シリアル出力
hserout [dec4 ad0,lf] '5 Byte out

LOOP '無限ループ

(I/O設定、変数定義などは省略)
そう (まこち)
2013-07-30 21:47:43
ブログ書くときもタブとかスペースとか、特に<<などの記号はキャンセルされちゃいます。なので今回のコードは画面キャプチャですw

ArduinoってのでもADCは
Varialbe = AnalogRead(PinNo);
で出来ちゃうのです。

ユーザーからハードウェアをある程度隠してくれるプログラミング言語もプログラム作るのは早くていいんだけど、今回はCの勉強も兼ねてるのでまあ、こんなかんじです。

あと、BASICコンパイラよりはCコンパイラのほうが幾分かコードサイズが小さくなりそうかなぁ・・・と。

コメントを投稿

その他雑記」カテゴリの最新記事