インターバルタイマを使ったプログラミングでは、設定のため、幾つかのレジスタを設定する必要がある。レジスタとタイマの機能について、概観すると、以下のようになる。

H8/3052には5つのタイマユニット(ITU0~4)が内蔵されているが、デフォルトではOFFに設定されている。タイマユニットをONにしたい場合は、TSTR(タイマ・スタート・レジスタ)の該当するビットを1に設定する。
-
タイマの動作は、システムクロック(φ、もしくは外部クロック信号)を基準に動作する。システムクロックの周波数は25MHz(1秒間に2千5百万回の振動)なので、ゆっくりカウントしたい場合は、プリスケーラを使うことで、1/8まで周波数を落とす事が出来る。この場合は、ITU毎に設置されているTCRのTPSC1、TPSC0のビットを設定する。
(外部クロックを使う場合は、TCRのビット2~TPSC2を1に設定する)
-
TCNTのカウント方法を設定する。プリスケーラで周波数を遅くした(これを分周という。逆に周波数を上げる場合は、逓倍)クロック信号について、どのようにカウントするかを設定する。これは、TCRのビット4と3(CKEG1、CKEG0)で設定する。
-
GRA、GRBの設定を行う。いずれもITU毎に1つずつ実装されている。インターバルタイマを使う場合のGRAとGRBの動作は、以下の通り。(TCNTとGRA、GRBのコンペアマッチで、TIOCAとTIOCBを反転出力させ、設定次第で割り込みも発生。GRBのコンペアマッチで、TCNTを0にリセット)

- TCNTの値は、プリスケーラで設定された周期でカウントアップされる。
-
TCNTの値がGRAもしくはGRBに一致(コンペア・マッチ)した際、CCLR1およびCCLR0設定により、TCNTの値がリセットされる。(もしくは、リセットしない)
- TCNT=GRAの時、TIOCAの出力が反転、TSRのIMFAが1。TIERのIMIEAが1の時、割り込み発生
- TCNT=GRBの時、TIOCBの出力が反転、TSRのIMFBが1。TIERのIMIEBが1の時、割り込み発生
※
TIOCAとTIOCBは、コンペア・マッチなどのイベントが発生した事を、外部に通知する信号線。
- TSRの該当ビットを0にクリアする。
- TCNT == GRA の時 IMFA = 1
- TCNT == GRBの時 IMFB = 1
- TCNTが0xFFFFを超えた時、もしくは、0x0000を下回った時 OVF = 1
となるため、該当するビットをクリアする必要がある。割り込み許可状態(TIERの対応するビットが1)の状態だと、このビットをク
リアしない限り、割り込みイベント(インターバルタイマの)が継続して発生しているとみなされてしまう。
○プログラミングの実際
(1) 割り込みを使わずにTSRのフラグをチェックする方法。(こういうのをポーリングと呼ぶ)
【main.c】
#define ITU_TSTR (*(volatile unsigned char *)0xFFFF60)
#define ITU0_TCR (*(volatile unsigned char *)0xFFFF64)
#define ITU0_TSR (*(volatile unsigned char *)0xFFFF67)
#define ITU0_TIER (*(volatile unsigned char *)0xFFFF66)
#define ITU0_GRA (*(volatile unsigned int *)0xFFFF6A)
#define ITU0_GRB (*(volatile unsigned int *)0xFFFF6C)
void timer_init()
{
/* ITU0タイマーを初期化する
* ITU0のTCRレジスタに以下の値を設定
* プリスケール 1/8 => 0000 0011 (0x03)
* 立ち上りエッジでカウント => 0000 0000 (0x00)
* GRAコンペアマッチ => 0010 0000 (0x20)
*/
ITU0_TCR = ( 0x03 | 0x00 |
0x20);
/*
* クロック1/8で1msecのカウントができるようにGRAを設定
* 1秒間で25/8 M(10の6乗)回カウントする => 3.125M回
* 3125回カウントすると1msec経過したことになる
*/
ITU0_GRA = 3125;
/*
* ITU0のカウントアップを停止
* TSTRレジスタの1ビット目がITU0の開始、停止をコントロール
* 0なら停止、1なら開始
*/
ITU_TSTR = 0x00;
}
int main()
{
....
timer_init(); // インターバルタイマの初期設定
....
ITU_TSTR |= 0x1; //
ITU0を起動
while (1) {
....
if (ITU0_TSR &
0x01)) { // IMFAビットが1(GRAとTCNTの値が一致)である時、
ITU0_TSR = ITU0_TSR &
0xFE; // IMFAビットを0にクリア
|
※ 割り込みを使わない場合は、ベクタテーブルは修正する必要はない。(monitor.hは、無修正で、そのまま使えば良い)
(2) 割り込みを使う場合は、
【main.c】
#define ITU_TSTR (*(volatile unsigned char *)0xFFFF60)
#define ITU0_TCR (*(volatile unsigned char *)0xFFFF64)
#define ITU0_TSR (*(volatile unsigned char *)0xFFFF67)
#define ITU0_TIER (*(volatile unsigned char *)0xFFFF66)
#define ITU0_GRA (*(volatile unsigned int *)0xFFFF6A)
#define ITU0_GRB (*(volatile unsigned int *)0xFFFF6C)
void timer_init()
{
/* ITU0タイマーを初期化する
* ITU0のTCRレジスタに以下の値を設定
* プリスケール 1/8 => 0000 0011 (0x03)
* 立ち上りエッジでカウント => 0000 0000 (0x00)
* GRAコンペアマッチ => 0010 0000 (0x20)
*/
ITU0_TCR = ( 0x03 | 0x00 |
0x20);
/*
* クロック1/8で1msecのカウントができるようにGRAを設定
* 1秒間で25/8 M(10の6乗)回カウントする => 3.125M回
* 3125回カウントすると1msec経過したことになる
*/
ITU0_GRA = 3125;
/*
* ITU0のカウントアップを停止
* TSTRレジスタの1ビット目がITU0の開始、停止をコントロール
* 0なら停止、1なら開始
*/
ITU_TSTR = 0x00;
}
#pragma
interrupt(timer_imia_handler) //
以下に続く関数が、割り込みハンドラである事を示す。 void
timer_imia_handler() // 割り込みハンドラの定義 {
ITU0_TSR = ITU0_TSR & 0xFE;
printf(".");
}
int main()
{
....
set_imask_ccr(1); //
全ての割り込みを禁止
timer_init(); // インターバルタイマの初期設定
....
set_imask_ccr(0); //
全ての割り込みを許可
ITU0_TIER |= 0x1; //
ITU0_TSRのIMFAが1になった時に割り込み発生
ITU_TSTR |= 0x1; //
ITU0を起動
while (1) {
....
|
【monitor.h】
.....
void
timer_imia_handler();
.....
const fp VectorTable[] = // ベクタテーブルの定義
{
(fp)PowerON_Reset, // vector 0 Reset
(fp)0L, // vector 1 Reserved
.....
(fp)0L, // vector 23 [reserved]
(fp)timer_imia_handler,
// vector 24 ITU0 IMIA0
(fp)0L, // vector 25 ITU0 IMIB0
.....
|
さらなるステップアップ、エコな生活を実現したいあなたへ。(いささか大げさではあるが)
最終更新:2014年10月07日 16:08