連載
» 2006年08月08日 00時00分 公開

T-Engineプログラミング入門(3):必修技術:タスク制御とチャタリング対策 (2/5)

[中村 大真 パーソナルメディア株式会社,@IT MONOist]

プログラムのコンパイルから実行まで

 今回は、以下のソースコード(リスト1)をベースに話を進めます。まずはこのプログラムを実行できるようにし、その後で重要なポイントの解説を行います。さらに、いくつかの改良を施すことにします。

 なお、プログラムを実行するまでの一連の作業は、基本的に前回の「計数器プログラムのコンパイル&実行」とほぼ同じです。今回は要点のみにとどめますので、詳しくは前回を参照ください。


/*
 * スロットマシン(簡易版) (T-Kernel ベース)
 */
#include <tk/tkernel.h>
volatile ID tid_left, tid_right;
volatile int time_left, time_right;
/* 7セグメントLEDの各パターン */
const int p[] = {0xff - 0x01, 0xff - 0x80, 0xff - 0x40,
                 0xff - 0x10, 0xff - 0x08, 0xff - 0x02};
/* 左ドラムの処理タスク */
void task_left( INT stacd, VP exinf )
{
  ER er; int count_left;
  time_left = 30; count_left = 0; 
  for (;;) {
    /* スリープ */
    er = tk_slp_tsk( time_left );
    /* タイムアウトの場合 */
    if (er == E_TMOUT) {
      /* 左ドラムを次へ進める */
      count_left++; if (count_left >= 6) count_left = 0;
      /* 左7セグメントLEDに表示する */
      out_h( 0x16100002, p[count_left] );
    /* 割り込みハンドラから起床された場合 */
    } else if (er == E_OK) {
      /* 左ドラムを止める */
      if (time_left == 30) time_left = TMO_FEVR;
      /* 左ドラムの回転を再スタートさせる */
      else if (time_left == TMO_FEVR) time_left = 30;
    }
  }
}
/* 右ドラムの処理タスク */
void task_right( INT stacd, VP exinf )
{
  ER er; int count_right;
  time_right = 30; count_right = 0; 
  for (;;) {
    /* スリープ */
    er = tk_slp_tsk( time_right );
    /* タイムアウトの場合 */
    if (er == E_TMOUT) {
      /* 右ドラムを次へ進める */
      count_right++; if (count_right >= 6) count_right = 0;
      /* 右7セグメントLEDに表示する */
      out_h( 0x16100000, p[count_right] );
    /* 割り込みハンドラから起床された場合 */
    } else if (er == E_OK) {
      /* 右ドラムを止める */
      if (time_right == 30) time_right = TMO_FEVR;
      /* 右ドラムの回転を再スタートさせる */
      else if (time_right == TMO_FEVR) time_right = 30;
    }
  }
}
/* 左ボタンに対する割り込みハンドラ */
void int_left( UINT dintno )
{
  /* 割り込み要求クリア */
  ClearInt( dintno );
  /* 左ドラムの処理タスクを起床 */
  if (time_left == 30) tk_wup_tsk( tid_left );
}
/* 右ボタンに対する割り込みハンドラ */
void int_right( UINT dintno )
{
  /* 割り込み要求クリア */
  ClearInt( dintno );
  /* 右ドラムの処理タスクを起床 */
  if (time_right == 30) tk_wup_tsk( tid_right );
}
/* トグルスイッチ(SW7)に対する割り込みハンドラ */
void int_toggle( UINT dintno )
{
  /* 割り込み要求クリア */
  ClearInt( dintno );
  /* 左ドラムの処理タスクを起床 */
  if (time_left == TMO_FEVR) tk_wup_tsk( tid_left );
  /* 右ドラムの処理タスクを起床 */
  if (time_right == TMO_FEVR) tk_wup_tsk( tid_right );
}
/* メイン関数 */
ER main( INT ac, UB **av )
{
  T_CTSK ct_left = { NULL, TA_HLNG | TA_RNG0, task_left, 130, 4096 };
  T_CTSK ct_right = { NULL, TA_HLNG | TA_RNG0, task_right, 130, 4096 };
  T_DINT di_left = { TA_HLNG, int_left };
  T_DINT di_right = { TA_HLNG, int_right };
  T_DINT di_toggle = { TA_HLNG, int_toggle };
  if (ac >= 0) { /* ロード時 */
    /* 左ドラムの処理タスクを生成, 起動 */
    tid_left = tk_cre_tsk( &ct_left );
    tk_sta_tsk( tid_left, 0 );
    /* 右ドラムの処理タスクを生成, 起動 */
    tid_right = tk_cre_tsk( &ct_right );
    tk_sta_tsk( tid_right, 0 );
    /* 左ボタンに対する割り込みハンドラを定義 */
    tk_def_int( 164, &di_left );
    SetIntMode( 164, IM_EDGE | IM_LOW ); ClearInt( 164 ); EnableInt( 164, 0 );
    /* 右ボタンに対する割り込みハンドラを定義 */
    tk_def_int( 165, &di_right );
    SetIntMode( 165, IM_EDGE | IM_LOW ); ClearInt( 165 ); EnableInt( 165, 0 );
    /* トグルスイッチ(SW7)に対する割り込みハンドラを定義 */
    tk_def_int( 182, &di_toggle );
    SetIntMode( 182, IM_EDGE | IM_LOW ); ClearInt( 182 ); EnableInt( 182, 0 );
    return 0;
  } else { /* アンロードは未サポートとする */
    return E_NOSPT;
  }
} 
リスト1 スロットマシン(簡易版)のソースコード
C:\cygwin\usr\local\te\kappl\slot\src\slot.c

 「簡易版」としているのは、ソースを理解しやすくするために次の2つの処理を省略しているからです。

  • ドラムの回転を少しずつ遅くする処理を省略(ボタンが押されるとドラムの回転をすぐ止める)
  • トグルスイッチのチャタリング防止処理の省略
※コラム:スイッチのチャタリング
スイッチがONからOFFになる瞬間を検出する場合、理想的には信号がHighからLowになる瞬間を(エッジセンスで)検出するだけでよいはずです。しかし、現実にはスイッチの接点の振動があるので、ONからOFFになる瞬間だけでなく逆にOFFからONになる瞬間も含めて何度か信号がHighからLowになり、これらを誤って検出してしまうことがあります(図4)。これを「チャタリング(chattering)」といいます。

スイッチのチャタリング 図4 スイッチのチャタリング

チャタリングの継続時間はスイッチの性能によりますが、長くて数十ミリ秒、大抵は数ミリ秒以内です。


作業ディレクトリの作成とソースファイルの用意

 T-Kernelベースのプログラムですので、前回と同じく/usr/local/te/kappl下にslotディレクトリ、その下にsrcおよびtbmx1を新規作成します。

$ cd /usr/local/te/kappl
$ mkdir slot slot/src slot/tbmx1 

 ディレクトリを作成したら、リスト1の内容のソースファイルを作成してC:\cygwin\usr\local\te\kappl\slot\src\slot.cに保存してください。

Makefileの作成とメイク

 リスト2の内容のMakefileを作成し、C:\cygwin\usr\local\te\kappl\slot\src\Makefileに保存してください。

include ../../etc/makerules
VPATH = ../src
slot: slot.o 
リスト2 Makefile
C:\cygwin\usr\local\te\kappl\slot\src\Makefile

 次に、メイクを行います。Cygwin上で、以下のコマンドを実行します。

$ cd /usr/local/te/kappl/slot/tbmx1
$ ln -s ../src/Makefile
$ gmake 

 自動的にコンパイル/リンクが行われ、実行ファイルslotが生成されます。

ファイル転送と実行

 作成した実行ファイルslotをTeaboardに転送します。詳しい手順は前回を参照してください。今回転送するファイルはslotなので、TeaboardのCLIで以下のコマンドを実行します。

[/SYS]% recv -c slot 

 ファイル転送が完了したら、早速実行してみましょう。

[/SYS]% lodspg slot 

 左右のプッシュボタンを押すと、各LEDの回転が止まります。また、右端のトグルスイッチを上に戻してから下に倒すと、左右のLEDが再び回転を始めます。ただし、現時点ではチャタリング防止処理を行っていないため、トグルスイッチをゆっくり上に戻すと、その瞬間も信号を拾ってしまう場合があります。

Copyright © ITmedia, Inc. All Rights Reserved.