階層構造を意識したLED点灯プログラムに挑戦しよう!:マイクロマウスで始める組み込み開発入門(6)(2/3 ページ)
マイクロマウスの市販組み立てキット「Pi:Co Classic」を完成させた北上くんとえみちゃん。向上心あふれる北上くんの開発方針により、階層構造を意識したオリジナルプログラムを作成することになった。今回からいよいよ【プログラミング編】に突入する!
LED点灯プログラム
基板ポート一覧や回路図など、見慣れないものを見て、えみちゃんは難しく考え込んでしまったようです。でもご安心ください。LEDを点灯させるプログラム自体はさほど難しいものではありません。
例えば、Pi:Co Classicの左端のLEDを点灯させるためのプログラムは、以下のようになります(ソースコード1)。
//ポートの初期化(LED) PFC.PEIORL.BIT.B0 = 1; //PE0を出力に設定(LED 左) //LED 点灯 PE.DRL.BIT.B0 = 1; //LED 左 点灯
ソースコード1 LED左を点灯するプログラム |
それではこのプログラムを、前回、北上くんが熱弁を振るった“階層構造”になるように記述していきます。まず、ポートの初期化を「init.c」に記述します。併せて、クロックの初期化もここで行います(ソースコード2)。
#include "iodefine.h" #include "init.h" /************************************************/ /* H/W初期化 (init_all) */ /************************************************/ /* 全てのH/Wの初期化を行う */ /************************************************/ void init_all(void) { init_clock(); //CPUの動作周波数を設定 init_io(); //I/Oポートを設定 } /************************************************/ /* クロック初期化 (init_clock) */ /************************************************/ /* CPUクロックを設定する(48MHz) */ /************************************************/ void init_clock(void) { int i; CPG.FRQCR.BIT.IFC = 1; //CPUクロックをX'talの周波数×4に設定する(初期値は×2) for(i = 0; i < 0xfffff; i++); //PLLの動作が安定するまで待つ } /************************************************/ /* I/Oポート初期化 (init_io) */ /************************************************/ /* 出力ポートを設定する */ /************************************************/ void init_io(void) { //LED PFC.PEIORL.BIT.B0 = 1; //PE0を出力に設定 PFC.PEIORL.BIT.B1 = 1; //PE1を出力に設定 PFC.PEIORL.BIT.B2 = 1; //PE2を出力に設定 PFC.PEIORL.BIT.B3 = 1; //PE3を出力に設定 }
ソースコード2 「init.c」に記述する初期化プログラム |
LEDの点灯/消灯は、前回説明した通り、ドライバモジュールに記述します。4つあるLEDをそれぞれ単独の関数で取り扱い、点灯/消灯の値を“引数”として渡します。
あらかじめ、LEDのポートのPE.DRL.BIT.B0〜B03を「drv.h」内に分かりやすい名前で定義しておきましょう(ソースコード3)。
//LEDポート #define LED_L PE.DRL.BIT.B0 //LED 左 #define LED_FL PE.DRL.BIT.B1 //LED 左前 #define LED_FR PE.DRL.BIT.B2 //LED 右前 #define LED_R PE.DRL.BIT.B3 //LED 右
ソースコード3 「drv.h」内にLEDポート名を定義 |
同様に、点灯の“1”と消灯の“0”も定数として、「common.h」に定義しておきます(ソースコード4)。
//LED ON/OFF #define LED_ON 1 //LED ON #define LED_OFF 0 //LED OFF
ソースコード4 呼び出し側、実行側で同じ定義を使用するため、「common.h」に記述する |
それでは、「drv.c」にLED点灯/消灯関数を記述します(ソースコード5)。
void drv_led_l(int i_stat) { //LEDドライバ(左) LED_L = i_stat; }
ソースコード5 左LEDの点灯/消灯を行うLEDドライバモジュール。他の3つのLEDも同様に記述する |
このドライバモジュールを呼び出すのが、「ctrl.c」に記述するコントロールモジュールです(ソースコード6)。
void ctrl_led_l(int i_stat) { //LED処理(左) drv_led_l(i_stat); }
ソースコード6 左LEDの点灯/消灯を行うコントローラモジュール。他の3つも同様に記述する |
「drv.h」「ctr.h」には、それぞれに必要な関数のプロトタイプ宣言と外部参照を記述しておきます。
さぁ、これでOKだ! 後はアプリケーション次第で自由にLEDを点灯/消灯できるよ。
……。
ん? どうしたの?
センパイ……。やっぱり、階層構造化プログラムって面倒な気がしちゃいます。あっちに記述したり、こっちに記述したりでややこしいですし。
まぁ、ここだけ見るとそう思っちゃうかもね。
でも、実際にアプリケーションを作ったら、コントローラモジュールとドライバモジュールを分離する必要性や便利な点が実感できると思うよ。
そうですかねぇ……。
そうそう、もうすぐLEDが光るからさ!
頑張ってそこまでやってみようよ。
は〜い……。
Copyright © ITmedia, Inc. All Rights Reserved.