タイマ割り込みを、TIM1/TIM2/TIM3/TIM4 でやる方法を比較する

タイマの使い方にはいろいろあります.
最も基礎的な使い方は、定期的に割り込みをかけることといえます.

STM8Sの中には、TIM1,TIM2,TIM3,TIM4 という4つのタイマが内蔵されています.

これらのタイマは、TIM1が王様的に多機能なんですが、TIM2→TIM3→TIM4の順に機能がショボくなっていきます.
当然ライブラリ関数も違っています.
その違いを理解して、ライブラリ関数を使いこなさなくちゃいけません.
それがこのページの目的です.


タイマのブロック図

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

TIM2,3,4もだいたいこれとおなじブロック図です.




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

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


以下のソースコードは、project名test20のmain.cです.

●#include "stm8s.h"
ライブラリを利用するためにインクルードします.

●@CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSI, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE);
ACLK_HSIPrescalerConfig( CLK_PRESCALER_HSIDIV1 );
BCLK_SYSCLKConfig( CLK_PRESCALER_CPUDIV1 );
@は内部クロックの16MHzをつかうように設定します.
Aは16MHzを1分周して(=分周せずに)fMASTER=16MHzに設定します.fMASTERはタイマに供給されます.
BはfMASTERを1分周して(=分周せずに)fCPU=16MHzに設定します.fCPUはCPUに供給されます.
クロック設定についてはこちらのページを参照して思い出してください.

GPIO_Init(GPIOD, GPIO_PIN_0, GPIO_MODE_OUT_PP_HIGH_FAST);
LEDをチカチカ点滅させるためにPD0を出力に設定します.
GPIOについてはこちらのページを参照して思い出してください.

●TIM1_DeInit();
TIM1_TimeBaseInit( C1599, DTIM1_COUNTERMODE_UP, E4999, F0 ); // 16MHz/1600/5000=2Hz
TIM1_ITConfig(TIM1_IT_UPDATE, ENABLE);
TIM1_Cmd(ENABLE);
TIM1の設定です.
CfMASTERを1600分周して16MHz/1600=10kHzがカウンタに供給されるように設定します.
Dカウンタがカウントアップするように設定します.
Eカウンタが0〜4999までカウントするように設定します.
F割り込みをかけるときに間引き数を設定するのに使いますが、ここでは0にしておきます.
すると、16MHz/1600/5000=2Hzで割り込みがかかります.


●TIM2_DeInit();
TIM2_TimeBaseInit( GTIM2_PRESCALER_1024, H7812 ); // 16MHz/1024/7812=2Hz
TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE);
I//TIM2_Cmd(ENABLE);
TIM2の設定です.
GfMASTERを1024分周して16MHz/1024=15625Hzがカウンタに供給されるように設定します.
Hカウンタが0〜7813までカウントするように設定します.
Iただし、project test20ではTIM1を動かすのが目的なのでTIM2は止めておきます.
すると、16MHz/1024/7813=2Hzで割り込みがかかります.

●TIM3_DeInit();
TIM3_TimeBaseInit( JTIM3_PRESCALER_1024, K7812 ); // 16MHz/1024/7812=2Hz
TIM3_ITConfig(TIM3_IT_UPDATE, ENABLE);
L//TIM3_Cmd(ENABLE);
TIM3の設定です.
J
fMASTERを1024分周して16MHz/1024=15625Hzがカウンタに供給されるように設定します.
K
カウンタが0〜7813までカウントするように設定します.
Lただし、project test20ではTIM1を動かすのが目的なのでTIM3は止めておきます.
すると、16MHz/1024/7813=2Hzで割り込みがかかります.

TIM4_DeInit();
TIM4_TimeBaseInit( MTIM4_PRESCALER_128, N255 ); // 16MHz/128/256=488Hz
TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);
O//TIM4_Cmd(ENABLE);
TIM4の設定です.
MfMASTERを1024分周して16MHz/128=125kHzがカウンタに供給されるように設定します.
N
カウンタが0〜256までカウントするように設定します.
Oただし、project test20ではTIM1を動かすのが目的なのでTIM4は止めておきます.
すると、16MHz/128/256=488Hzで割り込みがかかります.
あとで説明しますが、TIM4では2Hzで割り込みをかけていません.
それはこれ以上遅くカウントできないからです.

●void TIM1_interrupt(void) interrupt 11  {
PGPIO_WriteReverse(GPIOD, GPIO_PIN_0);
QTIM1_ClearFlag(TIM1_FLAG_UPDATE);  }
TIM1割り込みルーチンです.
TIM1割り込みがかかるとここに飛んできます.
TIM1割り込みだと規定しているのが
interrupt 11 の文字です.
やっていることは、PではLEDを反転していますので、LEDは1Hzで点滅します.
Qでは次回の割り込みのためにフラグをクリアしています.

●void TIM2_interrupt(void) interrupt 13  {
GPIO_WriteReverse(GPIOD, GPIO_PIN_0);
TIM2_ClearFlag(TIM2_FLAG_UPDATE);  }
TIM2割り込みルーチンです.
TIM2割り込みがかかるとここに飛んできます.
TIM2割り込みだと規定しているのが
interrupt 13 の文字です.
やっていることは、TIM1割り込みと同じです.

●void TIM3_interrupt(void) interrupt 15  {
GPIO_WriteReverse(GPIOD, GPIO_PIN_0);
TIM3_ClearFlag(TIM3_FLAG_UPDATE);  }
TIM3割り込みルーチンです.
TIM3割り込みがかかるとここに飛んできます.
TIM3割り込みだと規定しているのが
interrupt 15 の文字です.
やっていることは、TIM1割り込みと同じです.

●void TIM4_interrupt(void) interrupt 23  {
GPIO_WriteReverse(GPIOD, GPIO_PIN_0);
TIM4_ClearFlag(TIM4_FLAG_UPDATE);  }
TIM4割り込みルーチンです.
TIM4割り込みがかかるとここに飛んできます.
TIM4割り込みだと規定しているのが
interrupt 23 の文字です.
やっていることは、TIM1割り込みと同じです.
488Hzで割り込んでくるので、LEDは244Hzで点滅します.



TIM1,TIM2,TIM3,TIM4の違いのまとめ

上記でTIM1,TIM2,TIM3,TIM4にライブラリ関数の違いがあることがわかったと思います.
それを整理します.

違いがある関数はこの関数です.
TIM1_TimeBaseInit( C1599, DTIM1_COUNTERMODE_UP, E4999, F0 ); // 16MHz/1600/5000=2Hz
TIM2_TimeBaseInit( GTIM2_PRESCALER_1024, H7812 ); // 16MHz/1024/7812=2Hz
TIM3_TimeBaseInit( JTIM3_PRESCALER_1024, K7812 ); // 16MHz/1024/7812=2Hz
TIM4_TimeBaseInit( MTIM4_PRESCALER_128, N255 ); // 16MHz/128/256=488Hz

つぎは引数をタイマ別にまとめた表です.
TIM1が王様で、TIM4は機能がすごくショボイってことがわかると思います.
なので、定期的な割り込みのような単純な作業はなるべくTIM4に任せて、複雑な処理にTIM1を割くのがよいわけです.
TIMx_TimeBaseInit
(引数)
TIM1
TIM2
TIM3
TIM4
第1引数
CfMASTERを分周する比率 (0〜65535)

0なら分周しない
1なら2分周する
Nなら(N+1)分周する
GfMASTERを分周する比率.
設定可能なのは下記のどれか.
TIM2_PRESCALER_1
TIM2_PRESCALER_2
TIM2_PRESCALER_4
TIM2_PRESCALER_8
TIM2_PRESCALER_16
TIM2_PRESCALER_32
TIM2_PRESCALER_64
TIM2_PRESCALER_128
TIM2_PRESCALER_256
TIM2_PRESCALER_512
TIM2_PRESCALER_1024
TIM2_PRESCALER_2048
TIM2_PRESCALER_4096
TIM2_PRESCALER_8192
TIM2_PRESCALER_16384
TIM2_PRESCALER_32768

JfMASTERを分周する比率
設定可能なのは下記のどれか.

TIM3_PRESCALER_1
TIM3_PRESCALER_2
TIM3_PRESCALER_4
TIM3_PRESCALER_8
TIM3_PRESCALER_16
TIM3_PRESCALER_32
TIM3_PRESCALER_64
TIM3_PRESCALER_128
TIM3_PRESCALER_256
TIM3_PRESCALER_512
TIM3_PRESCALER_1024
TIM3_PRESCALER_2048
TIM3_PRESCALER_4096
TIM3_PRESCALER_8192
TIM3_PRESCALER_16384
TIM3_PRESCALER_32768

MfMASTERを分周する比率
設定可能なのは下記のどれか.

TIM4_PRESCALER_1
TIM4_PRESCALER_2
TIM4_PRESCALER_4
TIM4_PRESCALER_8
TIM4_PRESCALER_16
TIM4_PRESCALER_32
TIM4_PRESCALER_64
TIM4_PRESCALER_128

第2引数 Dカウント形式の設定.
設定可能なのは下記のどれか.
TIM1_COUNTERMODE_UP
 
→overflowしたらゼロに戻る

TIM1_COUNTERMODE_DOWN
  →
underflowしたらMAXに戻る

TIM1_COUNTERMODE_CENTERALIGNED1
TIM1_COUNTERMODE_CENTERALIGNED2
TIM1_COUNTERMODE_CENTERALIGNED3
  →overflowしたらdownカウントに変わり、
      underflowしたらupカウントに変わる.


----引数なし----

UPカウントだけしかできない

----引数なし----

UPカウントだけしかできない

----引数なし----

UPカウントだけしかできない

第3引数 Eカウンタが0〜Nまでグルグル回る (0〜65535)
Hカウンタが0〜Nまでグルグル回る (0〜65535) Kカウンタが0〜Nまでグルグル回る (0〜65535) Nカウンタが0〜Nまでグルグル回る (0〜255)
255までなので注意のこと
第4引数 F割り込みを間引く数 (0〜255)
0なら間引かずに割り込む
1なら1回間引いて割り込む
NならN回間引いて割り込む


----引数なし---- ----引数なし---- ----引数なし----



サンプルプログラムの動作結果

test20
これは
TIM1_Cmd(ENABLE);のコメントが外してありますので、TIM1が動きます.
LEDが1秒周期で点滅します.

test20b
これは
TIM2_Cmd(ENABLE);のコメントが外してありますので、TIM2が動きます.
LEDが1秒周期で点滅します.

test20c
これは
TIM3_Cmd(ENABLE);のコメントが外してありますので、TIM3が動きます.
LEDが1秒周期で点滅します.

test20d
これは
TIM4_Cmd(ENABLE);のコメントが外してありますので、TIM4が動きます.
LEDが1秒周期ではなく244Hz周期で点滅します.オシロがないと確認するのはつらいですが.
TIM4は、プリスケーラが最大で128までしかないことと、
カウンタが16bitではなくて8bitしかないから、1Hzまで周期を下げられなかったためです.

inserted by FC2 system