連載
必修技術:タスク制御とチャタリング対策: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.