モールス出力 2006.04.07
基板上の LED の点滅状態で「 CPU のおおよその動作を知りたい」ということで、大昔から使っているヤツです。点滅パターンはテーブルで与えますので、複数の自由な点滅パターンの切替使用が可能です。(最初は、計測装置の異常入力を検知するためのブザー駆動用でした) 10mS 毎に駆動されるのが前提ですので、時間の分解能は 10mS になります。テーブルのデータは全て 8bit (unsigned char) ですので、指定できる ON/OFF の時間幅は 10mS 〜 2.55S となります。 (このページのものは、出力が 1チャンネル のタイプです。出力を 8チャネル へ拡張したものは、このページの最後を見て下さい。) |
以下を見ていただければ、おおよその感じをつかんでいただけると思います。 「繰返し回数」に続いて「ON/OFF 時間」が並んでいるだけです。 (テーブル長は任意:制約無し) ┌────┬───┬────┬───┬ ┬──┐ │繰返回数│ON時間│OFF 時間│ON時間│ ・・・ │0x00│ └────┴───┴────┴───┴ ┴──┘ 繰返し回数 0 〜 255 (ゼロは無限繰返し) ON/OFF時間 1 〜 255 (10mS単位) エンドマーク 0 (固定) 例:SOS 00, 20, 20, 20, 20, 20, 20, 60, 20, 60, 20, 60, 20, 00 ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ON OFF ON OFF ON OFF ON OFF ON OFF ON OFF ↑ ↑ ├───────┤ ├───────┤ ↑ ↑ S O ↑ ↑ ↑ 繰返し回数(ゼロは無限) ENDmark SOS の実行結果 ON ┌┐┌┐┌┐┌──┐┌──┐┌──┐┌┐┌┐┌┐ OFF ─┘└┘└┘└┘ └┘ └┘ └┘└┘└┘└ |
起動 : テーブルアドレスをパラメータとして起動関数を呼ぶ 停止 : 停止関数を呼ぶ(パラメータ無し) Morse1ON(TabelTopAdr); Mose1OFF(); これだけです。 |
ワーク typedef unsigned char byte; byte *MorseTbladr; // モールス出力用 テーブルアドレス byte *MorseTblp; // モールス出力用 テーブル読出ポインタ byte MorseRect; // モールス出力用 繰返しカウンタ byte MorseOffct; // モールス出力用 OFF時間カウンタ byte MorseOnct; // モールス出力用 ON 時間カウンタ起動関数 与えられたテーブルアドレスを *MorseTbladr へセットし、ON/OFF 時間カウンタをゼロクリアします。本体関数が割込処理関数内より駆動される場合、各ワークは「割込禁止」状態で操作する必要があります。(通常のメイン関数より起動される場合は必要ありません) extern InterruptSave(void); // 割込フラグ保存、割込禁止 extern InterruptLoad(void); // 割込フラグ復帰 void Morse1ON(byte *tbl) { InterruptSave(); // 割込許可/禁止フラグ保存後、割込禁止 MorseOnct = 0; MorseOffct = 0; MorseTbladr = tbl; InterruptLoad(); // 割込許可/禁止フラグ復帰 }停止関数 *MorseTbladr をゼロクリアします。 void Morse1OFF(void) { MorseTbladr = 0; }本体関数 ( 10mS 毎に駆動されます) テーブルアドレス *MorseTbladr がゼロなら何もしません。 ON/OFF時間カウンタが共にゼロなら「新規テーブルでの動作開始」として、テーブルから読み出した「繰返し回数」を MorseRect へセットし、モールス出力を ON にしてから最初の ON時間を MorseOnct へセットし、次の OFF時間データの位置(アドレス)を *MorseTblp へセットします。 ON時間カウンタがゼロで無ければ、-1 後、結果がゼロならモールス出力を OFF してから次の OFF時間を MorseOffct へセットし、次の ON時間データの位置(アドレス)を *MorseTblp へセットします。 OFF時間カウンタがゼロで無ければ、-1 後、結果がゼロなら次の ON時間を MorseOnct へセットし、その値を調べます。ON時間がゼロでなければ次の ON の処理へ、ゼロならテーブルエンドなので繰返し回数を調べます。繰返し回数がゼロでなければ -1 し、結果がゼロでなければテーブルの最初から処理を繰り返します。結果が ゼロならモールス出力を停止します。 extern Morse1Drv(byte); // モールス出力(ポート駆動) void Morse1(void) { if (MorseTbladr == 0) { // 出力停止中 Morse1Drv(OFF); return; } // ----------------------------------- if (MorseOnct != 0) { // ON時間カウント中 // ----------------------------------- if (--MorseOnct == 0) { // ON時間カウントアップなら Morse1Drv(OFF); MorseOffct = *(MorseTblp++);// OFF時間セット } else { Morse1Drv(ON); } // ----------------------------------- } else if (MorseOffct != 0) { // OFF時間カウント中 // ----------------------------------- if (--MorseOffct == 0) { // OFF時間カウントアップなら MorseOnct = *(MorseTblp++); // ON時間セット if (MorseOnct == 0) { // テーブルエンドなら if (MorseRect != 0) { // 無限繰返しではなくて if (--MorseRect == 0) { // 繰返し回数終了なら MorseTbladr = 0; // 出力停止 Morse1Drv(OFF); return; } else { startMorse(); // テーブルTopから再動作開始 } } else { startMorse(); // テーブルTopから再動作開始 } } Morse1Drv(ON); } else { Morse1Drv(OFF); } // ----------------------------------- } else { // 新規出力開始(今までは停止中だった) // ----------------------------------- MorseRect = *MorseTbladr; // 繰返し回数 startMorse(); // テーブルTopから新規動作開始 } } // ------------------------------------ // テーブルTopから動作開始 // ------------------------------------ void startMorse(void) { MorseTblp = MorseTbladr +1; // テーブル読み出しP MorseOnct = *(MorseTblp++); // ON時間 Morse1Drv(ON); } |
実際に使うと 「なぁ〜んだ簡単じゃねぇか」 だと思いますが、私がよく使うのは次のようなパターンを切替えるものです。 const byte on02of48[] = { 0, 2, 48, 0 } ; const byte on02of20on02of50[] = { 0, 2, 20, 2, 48, 0 } ; const byte on02of20on02of20on02of50[] = { 0, 2, 20, 2, 20, 2, 48, 0 } ; const byte on02of98[] = { 0, 2, 98, 0 } ; : Morse1ON(on02of48); : : Morse1ON(on02of98); : |
簡単にテストするためのものです。H8/3694(3664)で動作します。 P85をモールス出力に、P87を10mS毎の反転出力に割当てています。 (これらのポートが既に使用中ならソフトの変更で空きポートへ振ってください) 他のポートには何もしていませんので、空きポートがあれば処理をお願いします。 |
2007.07.12 エエカゲンな書き方をしていたポインタ操作部分を修正しました。 |