C言語

タイマ制御の実装

タイマ制御は、メイン周期の10msのインターバル・タイマを制御します。
基本的に10ms周期のインターバル・タイマを開始して、10ms経過時のカウント完了の割り込み処理で10ms経過のフラグをセットしてメインに通知するような制御になります。

メイン周期タイマ開始処理の関数概要

関数名は、「G_DrTimerCtrl_MainCycleStart」です。
10msのカウント値をTDR00レジスタに設定する。
チャネル0のカウント完了割り込みを許可に設定する。
チャネル0のタイマを開始する。

以上がメイン周期タイマ開始処理の概要となります。
この開始処理は、マイコン起動時のメイン 開始前処理時と、HALTモードからの復帰時にメイン処理から呼ばれます。

メイン周期タイマ割り込み処理の関数概要

関数名は、「Int_DrTimerCtrl_MainCycle」です。
こちらは、チャネル0のタイマカウントが完了したときに発生する割り込み関数になります。
メイン周期フラグをONに設定するのみとなります。
メイン処理は、このメイン周期フラグがONの場合、10ms経過したと判断します。また、10ms経過したと判断した場合、メイン処理がメイン周期フラグをOFFさせます。

タイマ制御スリープ処理の関数概要

関数名は、「G_DrTimerCtrl_Sleep」です。
こちらの関数は、HALTモードに移行するときに、タイマ割り込み無効と、タイマ停止を行います。
HALTモード中に割り込みが発生するとHALTモードが解除されます。せっかく、HALTモードにしても10ms周期毎にタイマ割り込みが発生し、HALTモードがすぐに解除されてしまうため、メイン処理にてHALTモードに移行する前にこちらの関数を呼び出してタイマ制御を停止させます。
ちなみに、HALTモードを解除するのは、赤外線リモコンのみという設計となっています。

メイン周期フラグ取得処理の関数概要

関数名は、「U1G_DrTimerCtrl_GetMainCycleFlg」です。
こちらの関数は、メイン処理がメイン周期フラグを参照するため、このフラグのゲッター関数を用意しました。
メイン周期フラグを戻り値として返すのみになります。

メイン周期フラグクリア処理の関数概要

関数名は、「G_DrTimerCtrl_ClrMainCycleFlg」です。
メイン周期フラグをOFFにするのみになります。
メイン処理にて、10ms周期フラグがONと判断された場合にすぐにOFFすることによって、10ms周期フラグのON検出が1回のみとなるようにしています。

今回の設計では、グローバル変数を使用しないため、各モジュールにスタティック変数で用意し、セッター、ゲッター、クリア関数を用意することにしています。

タイマ制御の実装

「DrTimerCtrl.c」ファイルに先ほど説明した関数を実装していきます。
実装内容は次のようにします。

#include "iodefine.h"
#include "DrTimerCtrl.h"

#pragma interrupt Int_DrTimerCtrl_MainCycle( vect=INTTM00 )

#define U2S_DRTIMERCTRL_TDR00       ((U2)(0x09C3U))
#define U1S_DRTIMERCTRL_INT_ENABLE  ((U1)(0U))
#define U1S_DRTIMERCTRL_INT_DISABLE ((U1)(1U))
#define U2S_DRTIMERCTRL_CHANEL0     ((U2)(0x0001U))

static U1 u1s_DrTimerCtrl_MainCycleFlg;

void G_DrTimerCtrl_MainCycleStart( void )
{
    TDR00 = U2S_DRTIMERCTRL_TDR00;
    TMMK00 = U1S_DRTIMERCTRL_INT_ENABLE;
    TS0 |= U2S_DRTIMERCTRL_CHANEL0;
    return;
}

void G_DrTimerCtrl_Sleep( void )
{
    TMMK00 = U1S_DRTIMERCTRL_INT_DISABLE;
    TT0 |= U2S_DRTIMERCTRL_CHANEL0;
    return;
}

void Int_DrTimerCtrl_MainCycle( void )
{
    u1s_DrTimerCtrl_MainCycleFlg = U1_ON;
    return;
}

U1 U1G_DrTimerCtrl_GetMainCycleFlg( void )
{
    return u1s_DrTimerCtrl_MainCycleFlg;
}

void G_DrTimerCtrl_ClrMainCycleFlg( void )
{
    u1s_DrTimerCtrl_MainCycleFlg = U1_OFF;
    return;
}

特に難しい処理はないですが、TDR00に0x09C3Uを設定しているのは、チャネル0で使用する動作クロックは、250kHzのため、1カウント=4μsです。これにより、10msを設定すると2500カウントになるので、その値を設定しています。-1しているのは、最初の動作クロックでTDR00からTCR00レジスタにコピーされて、そこからカウントが開始するため、-1しています。

#pragma interruptは、割り込みを使用するときに使うハードウェア割り込みハンドラです。
チャネル0のタイマを使用するため、ベクタテーブル指定には、チャネル0のタイマの割り込みであるINTTM00を設定します。

次にヘッダーファイルの実装内容を次に示します。

#ifndef DRTIMERCTRL_H
#define DRTIMERCTRL_H

#include "common.h"

extern void G_DrTimerCtrl_MainCycleStart( void );
extern void G_DrTimerCtrl_Sleep( void );
extern U1 U1G_DrTimerCtrl_GetMainCycleFlg( void );
extern void G_DrTimerCtrl_ClrMainCycleFlg( void );

#endif

特に公開する定義もないため、関数のプロトタイプ宣言のみです。

簡単ではありますが、タイマ制御の実装については以上となります。

-C言語