連載
必修技術:タスク制御とチャタリング対策:T-Engineプログラミング入門(3)(5/5 ページ)
今回は基本中の基本であるタスク制御と、「チャタリング」という組み込みならではの問題への対処法を解説する
リスト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.