検索
連載

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

今回は基本中の基本であるタスク制御と、「チャタリング」という組み込みならではの問題への対処法を解説する

PC用表示 関連情報
Share
Tweet
LINE
Hatena
前のページへ |       

リスト3(完成版)


/*
 * スロットマシン(完成版) (T-Kernel ベース)
 */
#include <tk/tkernel.h>
volatile ID tid_left, tid_right, cid_toggle;
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] );
      /* 左ドラムの減速時 */
      if (time_left > 30) {
        /* 左ドラムの回転をさらに遅くする */
        time_left += 10;
        /* 左ドラムを停止する */
        if (time_left > 100) time_left=TMO_FEVR;
      }
    /* 割り込みハンドラから起床された場合 */
    } else if (er == E_OK) {
      /* 左ドラムの減速開始 */
      if (time_left == 30) time_left += 10;
      /* 左ドラムを最高速に戻す */
      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] );
      /* 右ドラムの減速時 */
      if (time_right > 30) {
        /* 右ドラムの回転をさらに遅くする */
        time_right += 10;
        /* 右ドラムを停止する */
        if (time_right > 100) time_right=TMO_FEVR;
      }
    /* 割り込みハンドラから起床された場合 */
    } else if (er == E_OK) {
      /* 右ドラムの減速開始 */
      if (time_right == 30) time_right += 10;
      /* 右ドラムを最高速に戻す */
      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 cyc_toggle( VP exinf )
{
  /* 前回の状態を保存しておく変数 */
  static int t1 = 0;
  int t2;
  /* 現在のスイッチの状態を取得 */
  t2 = in_w( 0x0021c224 ) & (1 << 22);
  /* 前回が High で, 今回が Low の場合 */
  if (t1 != 0 && t2 == 0) {
    /* 左ドラムの処理タスクを起床 */
    if (time_left == TMO_FEVR) tk_wup_tsk( tid_left );
    /* 右ドラムの処理タスクを起床 */
    if (time_right == TMO_FEVR) tk_wup_tsk( tid_right );
  }
  /* 今回の状態を保存して次回に備える */
  t1 = t2;
}
/* メイン関数 */
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_CCYC cc_toggle = { NULL, TA_HLNG, cyc_toggle, 10, 0 };
  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)を監視する周期ハンドラを生成, 起動 */
    cid_toggle = tk_cre_cyc( &cc_toggle );
    tk_sta_cyc( cid_toggle );
    return 0;
  } else { /* アンロードは未サポートとする */
    return E_NOSPT;
  }
} 
リスト3


Copyright © ITmedia, Inc. All Rights Reserved.

前のページへ |       
ページトップに戻る