目次

タイマー割込み

 タイマー割込みを利用する場合、4つあるタイマーが
 どういう動きをするのかを理解しなくてはなりません。

 アドレスマップを見て、各タイマーの動作を
 レジスタから理解します。



 リセット時の16進コードから、各タイマーの
 ビットサイズは、次のようになります。

 3つのタイマーには、汎用のタイマーの他に
 AnalogDevicesが決めた使ってほしい機能の
 名称が付けられています。

 各タイマーのレジスタには、LD、VAL、CON、CLRIが
 共通であります。
 これらのレジスタの機能は以下です。

 レジスタCONに、動作モードを設定します。
 CONに設定する内容は、以下です。

 CONで指定する動作は、どういうことを
 やりたいかで決まりますが、次の原則は
 忘れてはいけないでしょう。

 タイマーは、通常はダウンカウンタ処理。
 VALの値を参照することで、経過時間を知る
 ことができますが、ポーリングでは、値参照
 にかかり切りになるので、割込みを使って
 通知してもらうように設定するのが定石です。

 各タイマーの動作を見てみます。

timer0(RTOS)動作  timer0のブロック図は、以下。  ブロック図から読み取れることをリスト。  これらの動作モードを設定するには、T0CONレジスタ  に与えるパラメータを組合わせます。  レジスタのビット構成から、次の内容を読み取れます。  周期動作は、ダウンカウントして値が0になった時  レジスタLDの設定値を、カウンタにロードさせて  ダウンカウントを継続すると設定可能。  カウント値が0になったことを、割込みで通知して  もらうと、様々な処理を1つのコンピュータで実現  できます。割込み指定は、タイマーカウンタでは  なく、IRQモジュールのレジスタに設定です。  IRQENレジスタのTimer0ビットに1を設定すると  timer0割込みが発生。  AnalogDevicesのデータシートでは、ビット割当て  を確認できます。  Keilの開発環境では、次のようにレジスタに設定できます。 /* enable timer 0 */ IRQEN = RTOS_TIMER_BIT ;  Keilの開発環境では、AnalogDevicesのデータシートで  規定した、RTOSというtimer0の機能を考えた、ラベル名  を使っています。  T0LD、T0CONレジスタへのパラメータ設定は、次の  ようなコードにします。 /* initialize timer 0 */ { T0LD = 26112 ; /* select cyclic , HCLK / 256 */ T0CON = 0xc4 ; }  割込みが発生したときは、T0CLRIレジスタに  値を書き込み、割込み発生フラグをリセット  します。  具体的な関数は、次のように記述し。   void IRQ_Handler(void) __irq   {    /* clear timer 0 interrupt flag */ if ( (IRQSTA & RTOS_TIMER_BIT) == RTOS_TIMER_BIT ) { T0CLRI = 0xff ; } }  すべての割り込みは、ひとつの関数で扱います。  関数内部で、どの割込みが発生したのかを判断し  必要な設定をします。
timer1動作  timer1のブロック図は、以下。  ブロック図から読み取れることをリスト。  リスト内容から初期設定には、次の2点を最初に検討すれば充分。  レジスタでは、T1CONの各ビットの組み合わせで設定。  32ビット中の11から9で、利用クロックを指定。  32ビット中の3から0で、プリスケーラ分周比を指定。  レジスタT1CONの利用クロック、プリスケーラ分周比指定は  次のようなコードにすればよいでしょう。 T1CON = (1 << 9) | 15 ;  外部の32.768kHzを入力し、プリスケーラの分周比を1:32768に  設定します。  timer1を使わないのが、デフォルトになっているので  動かす場合は、T1CONレジスタの該当ビットを、セット  します。  初期設定と同時にtimer1を動かす場合、レジスタへの設定は  次のようになります。 T1CON = (1 << 9) | (1 << 7) |15 ;  timer1のカウンタは、アップあるいはダウンできるように  設計されています。  カウンタをアップで使うかダウンで使うかは、T1CONレジスタ  のビット8に設定する値で指定します。  カウンタ値がT1LDと一致すると、対応する割込みフラグが設定  されるので、割込みハンドラは次のように記述できます。   void IRQ_Handler(void) __irq   {    /* clear timer 1 interrupt flag */ if ( (IRQSTA & GP_TIMER_BIT) == GP_TIMER_BIT ) { /* clear flag */ T1CLRI = 0xff ; /* ??? */ } }  利用クロックに32.768kHzがあり、プリスケーラ分周比に1:32768を  指定できることから、リアルタイムクロックを構成できると読取れ  ます。  timer1をリアルタイムクロックで使う場合、時、分、秒、1/100秒の  扱いを、カウンタの中でBCDとするのか2進とするかを指定できます。  ビットの組み合わせで、時計として利用するのか、カウンタとして  使うのかを指定できます。  この他に、IRQの発生を0から31のいずれかを対象にして  補足できるようになっています。  対象となるIRQを指定し、IRQ発生時にカウンタ値をT1CAP  レジスタに格納する仕様になっています。  イベントキャプチャと呼ばれる動作で、指定IRQが発生する都度  カウンタ値を格納するので、周期や発生頻度を解析するのに利用  できます。  timer1は、A/D変換器でアナログ→デジタルの変換に利用する  クロックを生成しているので、A/D変換器を使う場合には注意  しなければ、希望する特性が得られない場面に遭遇します。
timer2(Wake-up)動作  timer2のブロック図は、以下。  ブロック図から読み取れることをリスト。  クロック関係は、上記の通りですが、ロードレジスタと  カウンタのビットサイズが32ビットなので、非常に長い  周期を選択できます。(timer2の別名はWake-up Timer)  timer2に、どんな機能があるのかを、T2CONレジスタの  記述から読み取ってみます。  クロックソースは、内部、外部、HCLKを選択可能。  外部クロックは、2つの方法で選択できます。  分周比は、1:1、1:16、1:256、1:32768ですが  256分周の場合、時間をhh:mm:ssでカウントし  23時から0時あるいは255時から0時に戻る時  割込みが発生するように指定するモードと関連  します。  クロックによるカウントは、ダウンカウント、アップ  カウントのどちらかを指定可能です。  周期モードかフリーランモードで使えますが  やはり周期モードで使うのが簡単なようです。
timer3(Watch_dog)動作  timer3のブロック図は、以下。  周期モードに設定すると、動作はtimer0と同じに  なりますが、クロックは32.768kHz固定です。  クロック固定なので、プリスケーラから出力できる  クロック周波数は、以下の3種だけになります。  1Hzのクロックが必要な場合、T3LDレジスタに  次の値を設定します。  時計を利用したい場合には、使えるタイマーでしょう。  割込みを使う場合、T3LDの値との兼ね合いで  次の図を参照してパラメータを設定します。
割込み処理  タイマーは4モジュールあり、0〜3と番号が  振られています。  これらのタイマーは、ダウンカウント処理で  動かすので、カウント値が0になったときに  割込みを発生させるようにします。  timer0からtimer3の割込みを発生させるため  には、該当ビットを1にします。  Keilの開発環境では、ヘッダファイルにラベル定義  されているので、それを使います。   #define RTOS_TIMER_BIT 0x00000004   #define GP_TIMER_BIT 0x00000008   #define WAKEUP_TIMER_BIT 0x00000010   #define WATCHDOG_TIMER_BIT 0x00000020  該当するヘッダファイルは、irq.hです。  対応するタイマとラベルは、以下です。  timer0からtimer3の割込みを使う場合、次のように  論理和で設定します。   IRQEN = RTOS_TIMER_BIT | GP_TIMER_BIT | WAKEUP_TIMER_BIT | WATCHDOG_TIMER_BIT ;  割込みハンドラは、関数IRQ_Handlerの中に記述します。 void IRQ_Handler(void) __irq { /* judge timer0 interruption */ if ( (IRQSTA & RTOS_TIMER_BIT) == RTOS_TIMER_BIT ) { /* clear flag */ T0CLRI = 0xff ; /* set event flag */ t0flag = ON ; /* ??? */ } /* judge timer1 interruption */ if ( (IRQSTA & GP_TIMER_BIT) == GP_TIMER_BIT ) { /* clear flag */ T1CLRI = 0xff ; /* set event flag */ t1flag = ON ; /* ??? */ } /* judge timer2 interruption */ if ( (IRQSTA & WAKEUP_TIMER_BIT) == WAKEUP_TIMER_BIT ) { /* clear flag */ T2CLRI = 0xff ; /* set event flag */ t2flag = ON ; /* ??? */ } /* judge timer3 interruption */ if ( (IRQSTA & WATCHDOG_TIMER_BIT) == WATCHDOG_TIMER_BIT ) { /* clear flag */ T3CLRI = 0xff ; /* set event flag */ t3flag = ON ; /* ??? */ } }
目次

inserted by FC2 system