ラーメンタイマラーメンタイマ麺類はお好きですか。本格的な生めんもカップ麺も、麺類の調理に欠かせないのがタイマです。この作品は、部品点数を極力減らしたラーメンタイマです。アジェンダラーメンタイマのハードウェアラーメンタイマのソフトウェアラーメンタイマのハードウェアこのアプリケーションの回路図は、以下のようになっています。押しボタン一個の操作で6個のLEDと圧電スピーカを駆動しています。このアプリケーションでは、以下の部品を使用しています。廣杉計器LEDの駆動方式このアプリケーションでは、LEDに電流制限抵抗を入れていません。これは、MC9RS08KA2の出力電流が多くないという事実を利用したものです。電位差(VOH-VOL)とLEDの順方向電圧(VF)をモデル化したものです。これら二つのグラフの交点でLEDが点灯します。それによって出力電流は約5mAに制限されます。これは、電源電圧が3Vであったときに限った計算です。マイコンとLEDに大電流が流れてしまい破壊する可能性がありますのでご注意ください。ラーメンタイマの実体配線図ラーメンタイマのソフトウェアこのアプリケーションのソフトウェアについて解説します。動作このアプリケーションは、押しボタン一個で操作します。最初にタイマの時間を設定します。押しボタンを押すと2分から7分の間でLEDの表示が移動していきます。タイマの時間測定が始まります。設定した時間になったら音楽が鳴り始めます。押しボタンを押すと音楽が止まります。状態遷移図このアプリケーションの状態遷移図は、このようになっています。それぞれの状態は、赤、緑、青の三色に分けられおり、以下のような意味づけがされています。待ちながら、低消費電力モードにいることを示します。おおむね5分で遷移します。約1μAの消費電流を実現しています。8ミリ秒ごとの周期的な処理を行っていることを示しています。比較的低消費電力になっています。おおむね300マイクロ秒ごとの周期的な処理を行っていることを示しています。頻繁に処理を行っている状態です。プログラムリストこのアプリケーションのプログラムは、以下のようになっています。作成したままの物を使用しています。デバッグ時設定の定義ここから、デバッグ時のレジスタの初期値が定義されます。バンドギャップ電圧は使用しません。LVD機能を使います。STOP状態でもLVD機能を使います。LVD機能でリセットを発生させます。LVD機能では割り込みを発生させません。LVDFがセットされていたら、クリアします。RESET*端子をリセット機能に使用しません。BKGD端子をBDM機能に使用します。STOP命令が実行できます。COP機能を使用しません。0ここでは、デバッグ時に使用するレジスタの初期値を決定しています。考えて設定する必要があります。続いて、リリース時のレジスタの初期値が定義されます。バンドギャップ電圧は使用しません。LVD機能を使います。STOP状態ではLVD機能を使いません。LVD機能でリセットを発生させます。LVD機能では割り込みを発生させません。LVDFがセットされていたら、クリアします。RESET*端子をリセット機能に使用しません。BKGD端子を汎用出力として使用します。STOP命令が実行できます。COP機能を使用しません。動作しないように設定します。(BDM)を使用しません。命令をプログラム内に埋め込む関数を定義しています。実際には、他の関数の中で展開されたうえでコンパイルされます。PTA2に押しボタンスイッチを接続しています。以下のプログラムをできるだけ抽象化できるように、ここでマクロの宣言を行っています。"flag"という変数をビット操作可能なフラグの集合として使用しています。ここでは、この変数の中のフラグの構成を宣言しています。このフラグは、LED表示装置が消灯されているかどうかを示します。LED表示プログラムは、このフラグの値を調べて、表示装置に送るデータを切り替えます。このフラグは、音楽を演奏するときに音を停止させます。発音プログラムは、このフラグを使って、音と音の間に停止時間を作ります。使用時のみ8ミリ秒ごとにRTIイベントを発生させます。RTIイベントが発生しても割り込みを発生させません。割り込みが必要な場合には、別途RTIEフラグをセットします。RTIのクロック源として1kHzの内部発振器を使います。時間測定には使用していません。非使用時には、消費電力を減らすため、内部発振器を止めます。RITFがセットされていたら、クリアします。モジュールの設定レジスタの初期値を定義しています。8ミリ秒ごとに割り込みを発生させています。消費電力を抑えるため、RTI機能と内部発振器を止めてしまいます。1/16プリスケーラを使用します。MTIMのクロック源としてバスクロックを使用します。このアプリケーションでは、バスクロックは4MHzです。使用する周期的割り込みをさせています。割り込み周期は、目的によって異なるので、その都度設定しなおしています。プリフィックス"P_"の付いた定数は、音階を表現するときに使用します。これらの定数を使って、楽譜を表現します。装備しているLEDの個数をあらわします。チャッタリング防止のための猶予時間を指定します。単位は、334マイクロ秒です。この時間が短かすぎるとチャッタリングを除去することができません。長すぎるとボタンを押してからの反応時間が長くなります。ボタンを操作した時に鳴らす確認音の長さを指定します。単位は、334マイクロ秒です。操作をしなくなってから、STOP状態に入るまでの待ち時間を指定します。単位は、8ミリ秒です。通常の待ち時間は数分程度に設定されます。ところが、待ち時間が長くなると、デバッグが難しくなります。このため、短縮動作時には早くSTOP状態に入るように切り替えられるようになっています。押しボタンの長押しを判定するための時間を指定します。単位は、334マイクロ秒です。このアプリケーションでは、ボタンの長押しを検出して動作を切り替えます。ボタンの長押し時間には個人差があるので、微調整が必要です。1/4秒の長さを指定します。単位は、1ミリ秒です。この定数は、時間を測定する際の基準となるため、時間の精度が必要です。ソフトウェアカウンタを使って、時間の計測を行っています。時間待ち状態では、1/4秒ごとにイベントを発生させます。1分の長さを指定します。単位は、1/4秒です。この定数は、時間待ちの基準時間を示します。短縮動作時には早く時間を進められるように切り替えられるようになっています。40(短縮動作時)ここでは、プログラムで使用する各種定数を定義しています。一部の定数は、環境変数"QUICK"の定義の有無によって設定が変更されます。状態コードを数え上げ型(enumeration)で定義して使用しています。State;いずれの状態も先の状態遷移図で紹介した状態です。RS08でプログラムを記述するときには無駄なコードが生成されます。コンパイラのオプションで"enum"のサイズを8ビットに指定する必要があります。状態コード変数に8ビットの"byte"を使用する方法もあります。楽譜の構造を定義するここでは、楽譜を表現するための構造体を定義しています。Music;RS08は、原則として64バイト以上の長さの配列を扱うことが出来ません。そのため、楽譜などの長い配列をそのまま表現する時には工夫が必要です。このプログラムでは、楽譜を三層構造の多重配列(配列へのポインタの配列)として表現しています。音階(period)と長さ(count)からなる、Sonoという構造体が宣言されています。この構造体で楽譜の音符ひとつ分が表現できます。Phraseは、Sono構造体へのポインタとして宣言されています。実際には、Sono構造体の配列を指して使用します。Sono構造体の配列は、64バイト境界をまたがない所に配置しなくてはなりません。Musicは、Phrase構造体へのポインタとして宣言されています。これもPhrase配列を指して使用されます。Phrase構造体の配列は、64バイト境界をまたがない所に配置しなくてはなりません。繰り返しの表現をすることもできます。それ以外のDIRECTアドレッシング領域($0020-$00BF)に配置されるものに大別されます。厳密に二つの領域を使い分けています。コンパイラはこのうち5バイト($0000-$0004)も作業領域に使用します。そのため、ユーザが自由に使えるRAM領域は9バイト($0005-$000D)だけです。点灯させるLEDの位置を記憶します。押しボタンスイッチのグリッチを取り除くためのタイマカウンタです。時間を計測するための汎用ソフトウェア・タイマ・カウンタです。待ち時間を計測するための1/4秒ごとに動作するソフトウェア・カウンタです。音楽演奏中に音符を指し示すポインタ変数です。音楽演奏中にPhrase構造体を指し示すポインタ変数です。待ち時間を計測するための1分ごとに動作するソフトウェア・カウンタです。待ち時間として設定された分単位の時間を記憶します。汎用ソフトウェア・フラグ群です。ステートマシンで使用される状態コードです。音楽演奏中に使用される発音の残り時間を計測するソフトウェア・カウンタです。演奏中の楽譜を記憶します。楽譜は、定数配列で宣言します。今回準備したのは、3曲です。一曲目は、不朽の名作、チャルメラ。これは、単一のPhraseで出来ています。(Phrase)0};二曲目は、ムソルグスキーの「展覧会の絵」から「卵の殻をつけたひよこの踊り」から。冒頭のPhraseを三番目のPhraseとして使いまわしています。(Phrase)0};三曲目は、ショパンの「別れの曲」から。この曲も一部、Phraseの使い回しをしています。設定する必要があります。ここでは、これらのレジスタに設定すべき値を宣言しています。LEDを消灯する際のレジスタの設定について定義しています。扱う際の便利な関数群を定義しています。RTI割り込みを受け付け可能にします。RTI機能を有効にしますが、割り込みは発生させません。RTIイベントが発生した場合TRUEを返します。RTIイベントフラグをクリアします。RTI機能を停止します。これらの関数を使ってリアルタイム割り込みに関する処理を抽象化しています。一般にこのような粒度の低い関数は避けたほうが無難であると思われます。コンパイルの段階で呼び出し側のプログラムに埋め込む事が可能です。マクロがそうであるように単なる呼び出し側プログラムの一部として実装されることになります。「マクロ」として記述したい場合には以下のような記述も出来ます。私は「関数」として定義したほうが理解しやすいと考えています。同じように関数群が定義されます。キーボード割り込みを受け付け可能にします。キーボード割り込みが発生した場合TRUEを返します。キーボード割り込みフラグをクリアします。キーボード割り込みを受け付け不可にします。この関数の場合にも、以下のようなマクロ定義を使用することができます。同様に関数群が定義されます。モジュロ・タイマ割り込みを受け付け可能にします。モジュロ・タイマ割り込みが発生した場合TRUEを返します。モジュロ・タイマ割り込みフラグをクリアします。モジュロ・タイマ割り込みを受け付け不可にします。この関数の場合にも、以下のようなマクロ定義を使用することができます。(MTIMSC=MTIMSC_TRST_MASK+MTIMSC_TSTP_MASK);LEDの表示を更新するここから、プログラムの本体が始まります。最初の関数は、put_ledです。LEDを点灯・消灯します。インライン展開しないように指定しています。この関数をインライン展開するとコードが大きくなるため、このような行を加えています。サブルーチン呼び出しとされてもそれほどコストがかかりません。圧電スピーカ出力を反転させるこの関数は、必要に応じて圧電スピーカ出力を反転させます。}}圧電スピーカからの発音時間は、変数sono_countで管理されています。この変数は、関数が呼び出されるたびに減少していき、"0"になったときに音が停止します。アプリケーションの初期化この関数では、アプリケーションで必要なモジュールなどの初期化を行っています。このような回りくどい書き方をする必要があります。ヘッダファイルが修正されたら、以下のようなシンプルな書き方をすることができます。それぞれの状態の初期化ルーチンを呼び出して状態遷移を表現しています。ここでは、それら初期化ルーチンのプロトタイプ宣言を行っています。処理ルーチンに備えます。モジュロ・割り込みの周期は、3000Hzに相当する周期です。同時にボタンを押したことを示す3000Hzの短い音を出します。押しボタンが放された事を検出したときには、WAIT状態に遷移します。チャッタリングを防止しています。処理ルーチンに備えます。ST_WAIT;}処理ルーチンでは、キーボード割り込みとリアルタイム割り込みを待ちます。PRESSED状態に遷移して押しボタンを監視します。時間待ちカウンタを進めます。この時、ほったらかし時間を経過していたらSTOP状態に遷移します。処理ルーチンに備えます。キーボード割り込みを待ちます。PROLOGUE状態に遷移します。処理ルーチンに備えます。モジュロ・割り込みの周期は、3000Hzに相当する周期です。同時にボタンを押したことを示す3000Hzの短い音を出します。LEDの位置を進めてWAIT状態に遷移します。VALIDATED状態に遷移します。処理ルーチンに備えます。モジュロ・割り込みの周期は、3000Hzに相当する周期です。同時にボタンを押したことを示す3000Hzの短い音を出します。LEDの位置を記録してからACTIVE状態に遷移します。処理ルーチンに備えます。モジュロ・割り込みの周期は、1000Hzに相当する周期です。キーボード割り込みとモジュロ・タイマ割り込みを待ちます。LEDの点灯位置を修復してPROLOGUE状態に遷移します。時間待ちカウンタを進めます。設定時間が過ぎたら、EPILOGUE状態に遷移します。ここでは、残り時間に従って、LEDの点灯状態を変更しています。処理ルーチンに備えます。割り込みは禁止します。その後、待ち時間に従って、演奏する楽譜を選んで変数にセットします。モジュロ・タイマ割り込みにより音の半周期ごとに処理を行います。音を出すためにポートを反転しています。押しボタンが押されたら、音楽の演奏を止めるためにPROLOGUE状態に遷移します。音の残り時間を確認し、楽譜から新たな音符を選んできます。状態遷移を行うための無限ループに入ります。通称PRMファイルと呼ばれるファイルを用意しなくてはなりません。PAGED_ROM領域として宣言しました。従って、ROM領域は0x3B00から0x3FF7までになっています。noritan.org。