モールス出力  2006.04.07



・ はじめに
 
基板上の LED の点滅状態で「 CPU のおおよその動作を知りたい」ということで、大昔から使っているヤツです。点滅パターンはテーブルで与えますので、複数の自由な点滅パターンの切替使用が可能です。(最初は、計測装置の異常入力を検知するためのブザー駆動用でした)

10mS 毎に駆動されるのが前提ですので、時間の分解能は 10mS になります。テーブルのデータは全て 8bit (unsigned char) ですので、指定できる ON/OFF の時間幅は 10mS 〜 2.55S となります。

(このページのものは、出力が 1チャンネル のタイプです。出力を 8チャネル へ拡張したものは、このページの最後を見て下さい。)

・ ON/OFF データテーブル
 
以下を見ていただければ、おおよその感じをつかんでいただけると思います。
「繰返し回数」に続いて「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);
       :
・ テスト用のプログラムソース  Morse1.lzh (7.5KB 2007.07.12)
 
簡単にテストするためのものです。H8/3694(3664)で動作します。
P85をモールス出力に、P87を10mS毎の反転出力に割当てています。
(これらのポートが既に使用中ならソフトの変更で空きポートへ振ってください)
他のポートには何もしていませんので、空きポートがあれば処理をお願いします。

・ 修正
 
2007.07.12 エエカゲンな書き方をしていたポインタ操作部分を修正しました。

出力8チャネル版 は こちら 。


Top      戻る