TIM1は外部へ信号を出力しない.タイマ割り込みをする.割り込みルーチンでLEDをチカチカさせる
----周期割り込みプログラムの書き方----


タイマのブロック図

予備知識として、タイマのブロック図を理解してから先に進みましょう.
タイマTIM1に入力されるクロックは、通常はfMASTERを使います.
または外部ピン(TIM1_ETR)に与えたクロックに使うことも可能です.
(他にも内部信号をクロックとして利用できますがここでは割愛します)

クロック周波数は設定で変えられますが、以下の解説では、クロック周波数について次のように決めて解説します.
外付け水晶
16MHz
fMASTER
16MHz
fCPU
16MHz
TIM1_ETR
1MHz
割り込み周期
projectによっていろいろ



タイマ割り込みを実現するソースコード

以下で解説するプログラムは、STM8S-DISCOVERYのLEDを1秒間隔で点滅させます.
サンプルプログラムはこちらに置いてあります.
このサンプルプログラムの、project test05が下記のソースコードです.
active projectの切り替えはこのようにして行います.


--------------------------------
#include "stm8s.h"
void main(void) {    // メインルーチン
  CLK_ClockSwitchConfig ( CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE );
  GPIO_Init(GPIOD, GPIO_PIN_0, GPIO_MODE_OUT_PP_HIGH_FAST);
  TIM1_DeInit();
  //TIM1_ETRClockMode2Config( TIM1_EXTTRGPSC_OFF, TIM1_EXTTRGPOLARITY_NONINVERTED, 0 );
  TIM1_TimeBaseInit( 1599, TIM1_COUNTERMODE_UP, 5000, 0 );
  TIM1_ITConfig(TIM1_IT_UPDATE, ENABLE);
  TIM1_Cmd(ENABLE);
  enableInterrupts();
  while(1) {    }     // Main loop
}

void TIM1_interrupt(void) interrupt 11 {     // タイマ割り込みルーチン
  TIM1_ClearFlag(TIM1_FLAG_UPDATE);
  GPIO_WriteReverse(GPIOD, GPIO_PIN_0);
}
--------------------------------

CLK_ClockSwitchConfig ( CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE );
クロック設定をしています.クロック設定についてはこちらのページを参照して思い出してください.
この引数でこの関数をcallすると、外部水晶発振子の16MHzがCPUやタイマーに供給されることになります.
タイマに16MHzが供給されるということを憶えておきましょう.

GPIO_Init(GPIOD, GPIO_PIN_0, GPIO_MODE_OUT_PP_HIGH_FAST);
PD0ピンを出力に設定しています.STM8S-DISCOVERYではPD0にはLEDが接続されていますので、このPD0を駆動するとLEDを点滅させられます.
GPIOについてはこちらのページを参照して思い出してください.

TIM1_DeInit();
タイマTIM1を使います.初期化します.この初期化は不要かもしれませんが念のため入れておきます.

//TIM1_ETRClockMode2Config( TIM1_EXTTRGPSC_OFF, TIM1_EXTTRGPOLARITY_NONINVERTED, 0 );
コメントアウトしてあります.その理由は、TIM1のクロック選択をfMASTERにするためです.
コメントを外すと、TIM1は外部ピンのTIM1_ETRをクロックとして選択します.

TIM1_TimeBaseInit( 1599, TIM1_COUNTERMODE_UP, 5000, 0 );
この関数を理解するのがこのページの目的です.あとで解説します.

●TIM1_ITConfig(TIM1_IT_UPDATE, ENABLE);
TIM1の割り込みが、カウンタがオーバーフローまたはゼロになった時に生じるように設定します
これは下図意味を持っています.
青い線はカウンタが0〜4999までグルグル回り続けている様子を表しています.
4999までどんついて0に戻る時に割り込みを発生します.

ほかにもいろいろな割り込みがつかえます.まずはUPDATEをマスターすればよろしいでしょう.
TIM1_IT_UPDATE TIM1の割り込みが、カウンタがオーバーフローまたはゼロになった時に生じるように設定します
TIM1_IT_CC1 タイマは、カウンタの値と閾値とを比較することで様々なパルス信号を発生させることができます.
TIM1には閾値比較回路をCC1〜CC4の4ヶ持っています.
この引数は、
TIM1の割り込みが、CC1の比較結果によってじるように設定します
TIM1_IT_CC2 TIM1の割り込みが、CC2の比較結果によってじるように設定します
TIM1_IT_CC3 TIM1の割り込みが、CC3の比較結果によってじるように設定します
TIM1_IT_CC4 TIM1の割り込みが、CC4の比較結果によって生じるように設定します
TIM1_IT_CCUpdate TIM1の割り込みが、比較回路が更新された時に生じるように設定します
TIM1_IT_TRIGGER TIM1の割り込みが、TIM1がトリガされた時に生じるように設定します
TIM1_IT_BREAK TIM1の割り込みが、BREAKがかかった時に生じるように設定します.
BREAKについてはこちらですこし解説しています.

TIM1_Cmd(ENABLE);
enableInterrupts();
タイマTIM1を動かし、割り込みをオンします.

void TIM1_interrupt(void) interrupt 11
この関数が、タイマ割り込み処理ルーチンです.
末尾のinterrupt 11が割り込み処理ルーチンであることを示す、Raisonance Cコンパイラ特有の修飾子です.
11番というのが、TIM1のクロックがオーバーフローしたら発生する割り込みの番号です.
割り込み発生源と割り込み番号の一覧表はこちらを参照してください.

TIM1_ClearFlag(TIM1_FLAG_UPDATE);
割り込みルーチンの冒頭では、割り込みフラグをクリアします.
これで次回の割り込みを待ち受ける状態になります.

GPIO_WriteReverse(GPIOD, GPIO_PIN_0);
PD0を論理反転します.PD0にはLEDが接続されています.
割り込みルーチンに飛んでくる度に論理反転するので、LEDが点滅します.



TIM1_TimeBaseInit()を詳しく知る

上で説明したソースコードでは、タイマのカウンタをグルグルと回して一定間隔で割り込みをかけてもらい、割り込み処理ルーチン内でLEDをオンオフさせるのが、やっていることの本質です.
LEDを1秒間隔でチカチカさせたいので、0.5秒オン→0.5秒オフ の繰り返しでチカチカさせることにします.
すると、割り込みを0.5Secごとにかけたくなります.

というわけで、どうやって割り込みを0.5秒ごとにかけるようにタイマのカウンタを回すんだ?が知りたいこととなります.
それを解説しましょう.

まず、上でも述べたとおり、CLK_ClockSwitchConfig() によって、タイマにfMASTER=16MHzが入力される状況を憶えておきます.
その上で、
TIM1_TimeBaseInit()の引数をいじるとどうなるかを理解すればよわけです.

再び、タイマのブロック図ですが、
CLK_ClockSwitchConfig()が設定するのは、fMASTERとfCPUです.
TIM1_TimeBaseInit()が設定するのは、TIM1内部の分周回路です.
したがって、
TIM1_TimeBaseInit()でいくら分周比を大きくしてもCPUの動作が遅くなったりしませんので、安心してください.


以下は、サンプルプログラムで
TIM1_TimeBaseInit()の引数によってタイマTIM1がどのように動作するかを動作確認した一覧表です.
この一覧表で、
TIM1_TimeBaseInit()の使い方をマスターしてください.
project

TIM1_TimeBaseInit()の引数 TIM1_ETRClockMode2Config()の引数
割り込み周期がどうなるか?    またその理由は?
test05
1599,
TIM1_COUNTERMODE_UP,
5000,
0
callしない 割り込み周期=0.5Sec
理由:
・16MHzが第1引数によって1/1600され10kHzになる.
・第2引数によってupカウントする.
・10kHzが第3引数によって5000カウントされるので2Hzになる.
・第4引数はゼロなので割り込みが間引かれることなく、0.5Sec周期で割り込みがかかる.

test05b
1599,
TIM1_COUNTERMODE_DOWN,
5000,
0
callしない 割り込み周期=0.5Sec
理由:
test05と違うのはカウンタがダウンカウントするところだけ.

test05c
1599,
TIM1_COUNTERMODE_CENTERALIGNED1,
5000,
0
callしない 割り込み周期=0.5Sec
理由:
test05と違うのはカウンタがup-downカウントするところだけ.
ボトムとピークで割り込みがかかるので、割り込み周期は0.5Secで変わらない.

なし
1599,
TIM1_COUNTERMODE_CENTERALIGNED2,
5000,
0
callしない 割り込み周期=0.5Sec
理由:
CENTERALIGNED2などの末尾の1と2と3の違いはなにか?
割り込みの細かい仕様に差違があるんだが、とても特殊な用途なので、説明は割愛します.末尾1だけ知っていればとりあえずOKです.

なし
1599,
TIM1_COUNTERMODE_CENTERALIGNED3,
5000,
0
callしない
test05d
159,
TIM1_COUNTERMODE_UP,
10000,
4
callしない 割り込み周期=0.5Sec
理由:
・16MHzが第1引数によって1/160され100kHzになる.
・第2引数によってupカウントする.
・100kHzが第3引数によって10000カウントされるので10Hzになる.
・第4引数は4なので割り込みが4回間引かれることで、都合0.5Sec周期で割り込みがかかる.
こういう実現方法もあるのだと知っておこう.

test05e
159,
TIM1_COUNTERMODE_UP,
10000,
0
callしない 割り込み周期=0.1Sec
理由:
test05dに似ているが、第4引数が0なので、0.1Sec周期で割り込みが発生する.

当然LEDのチカチカは高速になる.
番外編
test05f
159,
TIM1_COUNTERMODE_UP,
10000,
0
callしない 割り込み周期=0.1Sec
0.1Sec割り込みを受け付けるが、割り込みルーチンで10カウントすることで1秒周期のLED点滅を実現させようというプログラム.実際はこういう割り込みとプログラムの混ざった構造にすることが多いです.
具体的な実装は、cntという静的変数を新設し、0〜9までをぐるぐるとカウントさせています.
cnt=0,1の時だけLEDをオンにし、その他ではLEDをオフにしています.
なので、光り方が少し変わって見えます.
test05g
9,
TIM1_COUNTERMODE_UP,
10000,
0
TIM1_EXTTRGPSC_OFF,
TIM1_EXTTRGPOLARITY_NONINVERTED,
0
割り込み周期=0.1Sec
理由:
TIM1_ETRClockMode2Config()をcallしたので、外部ピンTIM1_ETRをクロックとして利用する
・TIM1_ETRには1MHzが入力されているとする.
・1MHzが第1引数により1/10にされ100kHzになる.
・第2引数によってupカウントする.
・100kHzが第3引数によって10000カウントされるので10Hzになる.
・第4引数はゼロなので割り込みが間引かれることなく、0.1Sec周期で割り込みがかかる.
project
TIM1_TimeBaseInit()の引数 TIM1_ETRClockMode2Config()の引数
割り込み周期がどうなるか?  またその理由は?


TIM1_TimeBaseInit()の引数の説明
第1引数 クロックの分周比を設定する 1〜65535
第2引数 カウントモードを設定する TIM1_COUNTERMODE_UP  
TIM1_COUNTERMODE_DOWN  
TIM1_COUNTERMODE_CENTERALIGNED1  
TIM1_COUNTERMODE_CENTERALIGNED2  
TIM1_COUNTERMODE_CENTERALIGNED3
第3引数 カウンタが0〜N-1までカウントするように設定する 1〜65535
第4引数 割込の間引き数を設定する 0〜255


TIM1_ETRClockMode2Config()の引数の説明
第1引数
外部ピンTIM1_ETRの分周比を設定
TIM1_EXTTRGPSC_OFF
TIM1_EXTTRGPSC_DIV2
TIM1_EXTTRGPSC_DIV4
TIM1_EXTTRGPSC_DIV8
第2引数
外部ピンTIM1_ETRの極性を設定
TIM1_EXTTRGPOLARITY_INVERTED
TIM1_EXTTRGPOLARITY_NONINVERTED
第3引数
外部ピンTIM1_ETRにノイズが多いと誤動作する可能性があるのは言うまでもない.
そこで、フィルタを入れる場合にこの引数で設定する.
0=フィルタなし
1〜15=フィルタあり

外部ピンTIM1_ETRをクロックとして使う場合は0であるべきだろう.

外部ピンTIM1_ETRをトリガ信号として使う場合には、1〜15の値を設定してもよい.
0: フィルタなし
1: fMASTERで2クロック後に再チェック
2: fMASTERで4クロック後に再チェック
3: fMASTERで8クロック後に再チェック
4: fMASTER/2で6
クロック後に再チェック
5: fMASTER/2で8クロック後に再チェック
6: fMASTER/4で6クロック後に再チェック
7: fMASTER/4で8クロック後に再チェック
8: fMASTER/8で6クロック後に再チェック
9: fMASTER/8で8クロック後に再チェック
10: fMASTER/16で5クロック後に再チェック
11: fMASTER/16で6クロック後に再チェック
12: fMASTER/16で8クロック後に再チェック
13: fMASTER/32で5クロック後に再チェック
14: fMASTER/32で6クロック後に再チェック
15: fMASTER/32で8クロック後に再チェック

inserted by FC2 system