;;; Wait Routine for 40us ;;;
;;; fosc = 10MHz, 400cycle loop ;;;
;;; 0.1usec * 2 * 200 = 40usec ;;;
WAIT40u:
LDI R19,200
W_LOOP40: ; Wait Loop
DEC R19 ; 1cycle
BRNE W_LOOP40 ; 1cycle
RET
上の例は AVR のアセンブラで マイコンから LCD へのコマンドとコマンドの送出間隔をコントロールするための wait ルーチンで、ここでは、10MHzで駆動している ATtiny2313 を 40usec 遅延させています。 上にも書きましたが、直観的に遅延時間が分かりやすいのが特徴です。 この wait ルーチンと 同じように NOP だけで作った100msec の wait ルーチンを組み合わせて 1/10秒ステップのストップウォッチもどきを作って消費電流を測定します。
電源電圧5V、繋がっている周辺回路は16行2列のLCD一つで、(基板上には他の回路も載っていますが、機能はオフしてあります) 消費電流は、10.0mA です。
こんどは、同じように 40usec の waitルーチンですが、遅延時間内は idle sleep の状態にしておきます。
;;; Timer-0 overflow interrupt ;;;
;;; exit sleep mode ;;;
Timer0Int:
reti
;;; Wait Routine for 40us, sleep ver. ;;;
;;; fosc = 10MHz ;;;
;;; 0.1usec * 8 * 50 = 40usec ;;;
;;; 1/8 prescale, 50cycle ;;;
WAIT40u:
ldi R19,0xCE ; 0xFF(256) - 0x32(50) = 0xCE(206)
out TCNT0,R19 ; set counter value : 50
ldi R19,0b00000010 ; prescaler : 1/8
out TCCR0B,R19 ; set timer0
sleep ; enter sleep mode
ret
wait ルーチンが呼ばれると TCNT0 にカウント回数を、TCCR0B にプリスケーラーの値をセットしてタイマールーチンに入ります。直後にsleepコマンドが実行され timer-0 の割り込み (Timer0Int) がかかるまで sleep モードにいます。 この一つ大枠のwaitルーチンで タイマーとsleepモードを組み合わせた 100msec waitループが組んであります。動作状況としては 100msec のうち ほぼ100usec だけ内部クロックが動作している事になります。この状態での消費電流は 5.9mA でした。約4mAの電流低減がはかれます。
これが正しいかどうか、マニュアルで確かめてみましょう。


動作周波数10MHz、電源電圧5Vの時のactive電流はおおよそ6mA、idle電流は2mAとなっているので差分としてはだいたい正しそうです。 絶対値として少し大きめに出ている原因の一つはLCDの消費電流がありますが、それでも少し大きすぎです。この件に関しては追実験が必要のようです。
このように、比較的待ち時間の長い waitループでは積極的に タイマーとsleepモードを組み合わせて利用すると消費電流の低減をはかれます。
次回はもう少しインターバルの長い条件 (1sec wait)では、どのような結果が出るか実験してみます。