Lチカプログラムの解説
前回のLチカプログラムを自分でも理解を深める為に解説してみたいと思います。
プログラム1
#define F_CPU 1000000UL // マイコンを1MHzで使用します
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRC = 0b11111111; // ポートC出力
PORTC = 0b00000000; // ポートC初期化
while (1)
{
PORTC = 0b00100000; // PC5 H
_delay_ms(500); // 500ms待つ
PORTC = 0b00000000; // PC5 L
_delay_ms(500); // 500ms待つ
}
return 0;
}
1行目の#define F_CPU 1000000UL
はutil/delay.hというヘッダーファイルを使用する為に必要な擬似命令です。マイコンのクロック周波数を何MHzで使用しているのかを宣言しています。前回使用したATmega88は工場出荷時クロック周波数が1MHzになっているそうです。
マイコンの設定が1MHzなのに#define F_CPU 8000000UL
としてしまうと、500ms待つ所が8倍の4000ms待つ事になってしまいます。LEDが4秒点灯、4秒消灯の8秒周期になってしまいます。
8行目のDDRC = 0b11111111;
のDDRCはデータ・ディレクション・レジスタCの意味で0b11111111を「=」で代入する事でポートCを出力モードに設定しています。0b00001111を代入すればPC0〜PC3は出力モード、PC4〜PC7は入力モードになります。
9行目のPORTC = 0b00000000;
はポートCをL出力で初期化しています。
11行目のwhile (1) { }
は{ }の中に書かれたコードを無限ループします。
13行目のPORTC = 0b00100000;
はATmega88のPC5(28番ピン)の出力をHにしています。PC5を選んだ理由はPC5のピン配置が配線しやすい位置だったからです。
14行目の_delay_ms(500);
は500ミリ秒つまり0.5秒待機しています。
15行目のPORTC = 0b00000000;
で再びPC5の出力をLにしています。
そして再び16行目の_delay_ms(500);
で0.5秒待機します。その後13行目に戻ります。これでおよそ1秒周期になります。
プログラム2
次のコードは上のコードより少し難しくなっていますが頑張って解説します( ̄O ̄;)
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRC = 0b00100000;
PORTC = 0b00000000;
while (1)
{
PORTC = PORTC | (1 << PC5);
_delay_ms(500);
PORTC = PORTC & ~(1 << PC5);
_delay_ms(500);
}
return 0;
}
途中までは同じなのでwhileの中のみ解説します。
12行目のPORTC = PORTC | (1 << PC5);
の「|」はOR演算子と言ってビット演算子の意味があります。「|」を挟んで左と右で比較をします。PORTCには9行目で0b00000000が代入されています。
#include <avr/io.h>
する事で「PC5」は「5」であると宣言されているので0b00000000 | (1 << 5)となります。前回使用したマイコンはATmega88なので「iom88.h」が選択されその中に宣言されていました。
「<<」はビットシフトの意味で左にシフトします。1は二進数で表すと0b00000001なのでこの「1」を5つ左にシフトします。すると( )の中は0b00100000となります。
0b00000000 | 0b00100000となります。
ORはビット同士を足し算して00100000となります。
そしてPORTCに0b00100000が代入され、マイコンのPC5の出力がHになります。ここまでが12行目のコードです。
500ms待って、14行目に行きます。
PORTC = PORTC & ~(1 << PC5);
の「&」はAND演算子と言ってこちらもビット演算子の意味です。「&」を挟んで左と右で比較します。
( )の中は先程と同じく0b00100000となります。しかし今度は( )の左に「~」が付いています。これはNOT演算子と言って演算数の反転を返します。1なら0、0なら1を返します。その為( )の中身を反転させ0b11011111となります。
PORTCの中身は0b00100000なので、0b00100000 & 0b11011111となります。
ANDはビット同士をかけ算して00000000となります。
そしてPORTCに0b00000000が代入され、マイコンのPC5の出力がLになります。
500ms待って12行目に戻ります。そして無限ループです。
まとめ
さてこの説明で理解いただけたでしょうか。そもそもこの説明で正しいのでしょうかσ(^_^;)
マイコンの勉強を再開したのはAVR制御でねじ切りがしたいからです。Gコードは使わずにロータリーエンコーダで入力してLCDに表示するスタンドアローンタイプの機械が作りたいです。
なので次はLCD表示をやりたいと思います。