ATTiny13Aという8ピンマイコンを使ってみる。
ADコンバータがちゃんと使えるかの確認。
最終的には8bit程度の分解能で十分なので、左詰で上位8ビットの読み出ししかしませんが、
10bit ADCに変更するのも十分可能でしょう。
ArduinoっぽくAnalogReadという関数にしてみた。
Atmel Studio 6.1を使っています。
以上のコードをコンパイルすると74バイト。コードの割にはでかくね?
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バイト。コードの割にはでかくね?
私が使っている 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設定、変数定義などは省略)
'***** 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設定、変数定義などは省略)
とりあえず、続きの不足分をば。
'ピークホールドリセット
pres = 1 'Peek Reset
pauseus 5
pres = 0 'Hold Free
'シリアル出力
hserout [dec4 ad0,lf] '5 Byte out
LOOP '無限ループ
(I/O設定、変数定義などは省略)
ArduinoってのでもADCは
Varialbe = AnalogRead(PinNo);
で出来ちゃうのです。
ユーザーからハードウェアをある程度隠してくれるプログラミング言語もプログラム作るのは早くていいんだけど、今回はCの勉強も兼ねてるのでまあ、こんなかんじです。
あと、BASICコンパイラよりはCコンパイラのほうが幾分かコードサイズが小さくなりそうかなぁ・・・と。