こんにちは。Yukiです。(投稿時間、こんばんは!ですけどね)
今回は、STM32F303K8のタイマー割り込みをやってみたいと思います。
今回使うタイマー
今回は、基本タイマーであるタイマー6(TIM6)を使用します。
TIM6の基本タイマーは
- 0-65535で選べるプリスケーラ
- 16bitタイマー
高性能過ぎて、基本タイマーとは?
割り込みの時間自体は、ARR(自動再ロードレジスタ)で設定可能です。
ということで、割り込み程度であれば、TIM6レジスタで十分です。
割り込みの要領
割り込みは、ARRレジスタに到達(もしかしたら0に戻ったらかもしれません)したら、割り込みされます。
つまり、プリスケーラとARRレジスタを組み合わせることにより、好きな割り込み周期を生成することが出来ます。
また、今回は使用しませんが、CCRレジスタなどでも割り込みできます。
つまり、PWM波を出力しながら割り込みという使い方も可能です。
レジスタ操作
まずはTIM6のAPB1クロックを入力(有効)にします。
//TIM6クロック入力(有効)
RCC->APB1ENR |= (1 << 4);
次に、ARRレジスタバッファを有効にします。
//TIM6_ARRレジスタバッファ有効
TIM6->CR1 |= (1 << 7);
次に、プリスケーラを操作し、1kHzにします。
今回は、入力周波数が8MHzなので8MHz ÷ 1kHz = 8000
ということで、7999を入力します。
TIM6->PSC = 7999; //1khz相当
次にARRレジスタを入力します。
今回は1sごとの割り込みをしたいので、1kHz = 0.001s
ということで、 1 ÷ 0.001 = 1000
つまり999を入力します。
TIM6->ARR = 999; //多分1sぐらい
次に、TIM6の割り込みを有効にします。
//TIM6 割り込み有効
TIM6->DIER |= (1 << 0);
次に、レジスタ更新を有効にします。
//レジスタ更新有効 (カウンタ初期化)
TIM6->EGR |= (1 << 0);
次に、割り込みのイベントハンドラを設定してあげます。
これは、便利なマクロが用意されているので、ありがたく使わせていただきます。
NVIC_EnableIRQ(TIM6_DAC_IRQn);
最後にTIM6のカウントを有効にします。
//TIM6 カウント有効
TIM6->CR1 |= (1 << 0);
これでTIM6の割り込み設定は終了です。
次に、割り込みのイベントハンドラを用意します。
イベントハンドラの一覧は、startup_stm32f303k8tx.sに記載されています。
今回は、TIM6なので、TIM6_DAC1_IRQHandlerを使用します。
ということで、次のように記載すると割り込みされます。
void TIM6_DAC1_IRQHandler(void){
}
割り込み内で、割り込みフラグを降ろさないと、無限ループします。
ということで、割り込みフラグを下げます。
void TIM6_DAC1_IRQHandler(void){
TIM6->SR = (~(1 << 0)); //割り込み解除
}
今回はこの中に、GPIOを反転させるプログラムを書きます。
//PB3を反転
GPIOB->ODR ^= (1 << 3);
動作
ボード上のLEDが1秒毎にチカチカしたら成功です。
LEDチカチカなんて面白くないので、今回は乗っけません。
ソースコード
いつも通りGoogle classroomでの配布です。
余談
PICよりも割り込みが使いやすいですね。これなら、割り込みを多用してもいいかもしれません。
ただ、割り込みハンドラの最初の方で、割り込みを無効にしてあげないと、2重で割り込みがかかったりするので、ちょっとよくわからない仕様ですね。
またこのように、宣言されていて、.weakが弱いという意味です。
main関数に同名の関数が用意されていれば、そちらを優先してコンパイルするという意味です。
アセンブラはさっぱりわからないので、解説する資格が無いような気もしますが、Defalut_handlerが無限ループを表しているようです。
ということは、main関数で用意されていないと、無限ループして、フリーズするということが分かりますね。
この辺は、ググれば、もっと詳しく調べている記事がでているのでそっちを見たほうが良いと思います。