LEDサンプル

やっぱり最初はこれよね。
LEDをPD0〜PD7に接続。

LEDサンプル

本当は抵抗が必要なはずだが、まぁいい。
とりあえずは光ればいい。
以下、ソースコード。

#include <avr/io.h>
#include <util/delay.h>

void delay_ms( int t )
{
	while( t-- ){
		_delay_ms( 1 );
	}
}

int main( void )
{
	DDRD	= 0b11111111;
	PORTD	= 0b00000000;

	char count	= 0;
	char binc	= 1;

	while( 1 ){
		PORTD = ( 1 << count );
		if( binc ){
			count++;
			if( 7 <= count ){
				binc = 0;
			}
		} else {
			count--;
			if( 0 >= count ){
				binc = 1;
			}
		}
		delay_ms( 50 );
	}

	return 0;
}

ATmega168Pは、内蔵RC発信器が8MHzとなっていたので、普通にCPUのFrequencyも8MHzだろうと思いこむ。
AVRStudioのProject Optionで、Frequencyを8000000Hzに設定して、F_CPUのdefineを設定したんだけど、実際やってみると、delay_msの待ちが余りに遅い。
具体的に言うと、8倍くらい。
データシートを読み返してみると、ヒューズビットにCKDIV8とかいうのがあって、こいつが0だと、実際には8で割った数がシステムクロックとなるらしい。
(システムクロック前置分周器:目的としては、消費電力節約用?)
ってんで、Frequencyを1000000Hzに設定しなおして、事なきを得る。

デバイスの最高周波数より高い周波数のクロックを入力する場合、前置分周器で押さえてやったりするみたいね。

というわけで、ヒューズビットのCKDIV8を立てて、Frequencyを8000000Hzにしてもちゃんと動きました。
この辺は、電源とかの兼ね合いで変えるべきかね。

AVRWikiにあるように、_delay_ms関数は、システムクロック数によって、待てる時間が異なり、しかもその時間は結構短い。
なので、1ms指定で指定ms分ループをしている。

_delay_ms関数は結局、周波数の定数F_CPUを参照して、それをもとにループ回数を決め、ループを回しているだけらしい。
このため、定数を_delay_msに渡す場合は、コンパイラが最適化し、ループ回数が決定している。
けど、変数を渡すようなコードを書くと、doubleに変換した引数とF_CPUの計算ルーチンが入るため、コードが膨らむ。
手軽に使えるけど、色々考えなければいけないようだ。


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS