メイン処理では、10ms周期毎に、ウォッチドッグタイマクリアと、赤外線リモコン受信データ解析処理、モータ制御処理、スリープ制御を行います。
メインの処理の流れ
メイン処理は、無限ループです。このメイン処理の前に全モジュールの初期化と、タイマ関連を開始します。
メイン処理では、次のような流れで処理します。
- ウォッチドッグタイマクリア
- 受信完了フラグ取得
- 受信継続フラグ取得
- 受信完了フラグがONの場合は、5~8を実行し、OFFの場合は、9以降を実行する
- 受信完了フラグをクリア
- スリープカウンタをクリア
- 赤外線リモコン受信データ解析処理を呼び出し、実行結果をセットする
- 実行結果のボタン種別により、各ボタンに応じたモータ制御処理を呼び出し、16へ遷移する
- 受信継続してない場合は、モータ制御の停止処理を呼び出す
- スリープカウンタをインクリメント
- スリープカウンタが30s経過した場合は、12~15を実行し、経過していない場合は16以降を実行する
- タイマ制御スリープ処理を呼び出し、タイマを停止する
- 赤外線リモコン受信制御のスリープ処理を呼び出す
- HALTモードに移行する
- HALTモード復帰後はメイン周期タイマを再開する
- メイン周期フラグ取得
- メイン周期フラグがONしていない場合(10ms経過していない場合)は、ONするまで(10ms経過するまで)ループさせ、1へ遷移させない。
- メイン周期フラグがONになったら、1へ遷移する
簡単ではありますが、処理の流れとしては以上となります。
メイン処理の実装
実際の実装の内容については次のようになります。
#include "common.h"
#include "AppRcvDataAls.h"
#include "DrRcvCtrl.h"
#include "DrMotorCtrl.h"
#include "DrWdtCtrl.h"
#include "DrTimerCtrl.h"
static void S_AppMain_AllInit( void );
#define U2S_APPMAIN_SLEEP_TIMEUP ((U2)(3000U))
static U2 u2s_AppMain_SleepCnt;
void AppMain(void)
{
U1 u1l_RcvFixFlg;
U1 u1l_MainCycleFlg;
U1 u1l_RcvCntinuFlg;
U4 u4l_BottomKind;
S_AppMain_AllInit();
EI();
while( 1 )
{
G_DrWdtCtrl_WdtTimClr();
u1l_RcvFixFlg = U1G_DrRcvCtrl_GetRcvFinFlg();
u1l_RcvCntinuFlg = U1G_DrRcvCtrl_GetRcvCntinuFlg();
if( u1l_RcvFixFlg == U1_ON )
{
G_DrRcvCtrl_ClrRcvFinFlg();
u2s_AppMain_SleepCnt = U2_CLR;
u4l_BottomKind = U4G_AppRcvDataAls_Main();
switch( u4l_BottomKind )
{
case U4G_APPRCVDATAALS_BTM_FOW:
G_DrMotorCtrl_Forward();
break;
case U4G_APPRCVDATAALS_BTM_BCK:
G_DrMotorCtrl_Back();
break;
case U4G_APPRCVDATAALS_BTM_RGT:
G_DrMotorCtrl_Right();
break;
case U4G_APPRCVDATAALS_BTM_LFT:
G_DrMotorCtrl_Left();
break;
default:
G_DrMotorCtrl_Stop();
break;
}
}
else
{
if( u1l_RcvCntinuFlg != U1_ON )
{
G_DrMotorCtrl_Stop();
}
u2s_AppMain_SleepCnt++;
if( u2s_AppMain_SleepCnt >= U2S_APPMAIN_SLEEP_TIMEUP )
{
G_DrTimerCtrl_Sleep();
G_DrRcvCtrl_Sleep();
halt();
G_DrTimerCtrl_MainCycleStart();
}
}
u1l_MainCycleFlg = U1G_DrTimerCtrl_GetMainCycleFlg();
while( u1l_MainCycleFlg != U1_ON )
{
u1l_MainCycleFlg = U1G_DrTimerCtrl_GetMainCycleFlg();
}
G_DrTimerCtrl_ClrMainCycleFlg();
}
}
static void S_AppMain_AllInit( void )
{
G_DrRcvCtrl_Init();
G_DrTimerCtrl_MainCycleStart();
G_DrRcvCtrl_Start();
}
S_AppMain_AllInit関数で、各モジュールで作成した初期化処理を呼び出します。
このS_AppMain_AllInit関数を実行後、AppMain関数に戻った後、EI関数を実行しています。
これは、割り込み許可にする命令です。基本的にRL78マイコンの起動時は割り込み禁止となっています。このため、どこかのタイミングで明示的に割り込み許可にしないと、割り込み機能のレジスタを割り込み許可にしても、割り込みを行わないので、今回は、割り込みを使用するタイマの開始直後にEI関数を実行しています。
その他は、処理の流れで説明した通り、実装しているつもりです。
簡単ではありますが、メイン処理の実装の実装については以上となります。