STM32 + LL でTIMの割り込みを動かしてみる
STM32マイコンのペリフェラル関連記事を一覧にまとめました。
今回は、TIMの割り込みを有効にして割り込みができるようにするということをやっていきたいと思います。TIM割り込みの実装をするときに少しはまったので丁寧に書いていきたいと思います。
使用するマイコンはSTM32F405RGTで、汎用タイマのTIM5を使用して割り込み処理の実装方法を書いていきたいと思います。
リファレンスマニュアルを確認する
TIMベースユニットを確認する
リファレンスマニュアルのタイマカウントのベース
TIMxに、クロックソースを入れたときの動作がどのようになっているのかを確認してみました。
クロックの周波数はプリスケーラで設定することができるということもわかりました。前回のPWM記事で使った周波数の計算式の出し方はリファレンスマニュアルのこの部分参考にしています。
アップカウントモードを使用する場合は、カウンターがオーバーフローをするごとに、UEVイベントを更新することができるということとが読み取れます。UEVイベントはCR1の設定次第で無効に設定をされてしまうので、有効に設定をする必要があるということが読み取れます。
レジスタの確認
例によって、レジスタの確認をしていきたいと思います。過去の記事で確認したレジスタについては省略します。
TIMx DIERレジスタ:割り込みイネーブルレジスタ
TIM更新割り込みイベントを動かすためには、ビット0のUIEを1に設定する必要があることがわかりました。
TIM SRレジスタ:ステータスレジスタ
ステータスレジスタを確認した結果、ビット0のUIFフラグは、先に確認した通り、更新イベントが発生するとハードウェアでビットが設定され、ソフトウェアでクリアしない限り次回の更新を行うことができなそうであるということがわかりました。
割り込みについて確認する
割り込みとイベントについて
割り込みコントローラについてみてみましょう。
NVICの設定をする必要があり、割り込みには優先度があることと、SysTickの1msの割り込みが標準で準備されているという事実がわかりました。機能詳細を見ていきます。
割り込みラインを設定するためには、イベントレジスタに割り込み許可の設定や、優先度、割り込みの条件などを伝えてあげる必要性があるようです。また、各機能においても更新イベントを設定して割り込み許可の設定をしてあげる必要もありそうです。
NVICプログラミングの詳細を確認するために、PM0214のドキュメントを見ていきたいと思います。
Nested vectored interrupt controller (NVIC)を確認する
NVICの説明を確認してみます。
今回必要そうなことは、割り込みには優先度があり、優先度は数字が小さいほど高いということかなと思います。STM32CubeMXの設定のときに設定をする必要がありそうです。また、割り込みの設定をするためには、CMSISで定義されている関数を使用することでできるということもわかりました。
STM32CubeMXの設定
PIN設定、TIMの設定は以下の通りです。
今回はNVICを使用するため、NVICSettingをしていこうと思います。
有効化するだけです。
TIM5のプリスケーラ、再リロードレジスタの設定値、Clock Configrationの説明については、TIMベースユニットで紹介をしたPWMの記事と同じであるため省略します。
Project Managerで使用するAPIをHALからLLに変更したのち、コードを生成してもらいましょう。
ソースコードを実装する
生成されたソースコードを確認する
MX_TIM5_Init関数の中身を確認していくと、TIM5にクロックを供給、NVICを有効化、優先度の指定をしたのちにプリスケーラなどの値をすべてセットしてくれていることがわかりました。
したがって、実装しなければならないことは更新イベントの作成を有効化することと、更新イベント発生時に割り込み処理を入れられるようにすることということがわかりました。
実装をする
タイマカウントをスタートして更新イベントの割り込みを有効化するプログラムは以下の通りです。
void IRQ_Start()
{
LL_TIM_EnableIT_UPDATE(TIM5);
LL_TIM_EnableCounter(TIM5);
}
やっていることはUIEの割り込み有効化ビットをを立てて割り込み処理を有効化したのちに、CNビットをたててTIMカウンタを有効化しています。
続いて、割り込みイベントの更新用プログラムを書いていきたいと思います。
stm32f4xx_it.cを開いてファイルの下のほうをみていくと、TIM5_IRQHandlerが生成されていると思います。TIM5の割り込みイベントのプログラムはここに記載していく必要があるので書いていきたいと思います。
void TIM5_IRQHandler(void)
{
/* USER CODE BEGIN TIM5_IRQn 0 */
if ( LL_TIM_IsActiveFlag_UPDATE(TIM5) == 1 ){
LL_TIM_ClearFlag_UPDATE(TIM5);
/* 割り込み処理を入れる */
}
/* USER CODE END TIM5_IRQn 0 */
/* USER CODE BEGIN TIM5_IRQn 1 */
/* USER CODE END TIM5_IRQn 1 */
}
UIFフラグが立っているかどうかを確認して立っていた場合はフラグをリセットして割り込み処理を中にいれるという処理をおこなっています。
割り込みを使用してLチカをしてみる
割りこみ処理の設定ができたので実際に割り込み処理が動いているかどうかを確認するためにLチカをしていきたいと思います。
今回は、Lチカのプログラムを別のファイルに作成して先程のTIM5_IRQHandler関数の割り込み処理を入れるというところにLチカの関数を呼ぶようにしていきたいと思います。
実装した関数は次の通りです。
void ltika(void)
{
// 変数counterは外部変数として定義してあるものとする。
counter++;
if( counter > 999 ){
LL_GPIO_SetOutputPin(LED_GPIO_Port, LED_Pin);
} else {
LL_GPIO_ResetOutputPin(LED_GPIO_Port, LED_Pin);
}
if( counter > 1999 ) counter = 0;
}
今回のプリスケーラと再リロードレジスタの設定では割り込み周期が1KHzとなっていることを利用してカウンターの値が0から999まではLEDをオフに、1000 ~ 1999まではLEDをオンにすることでLチカを行っています。
実際に組み込んで動作確認をしてみてください。Lチカが1秒ごとにできればOKです!
おわりに
LLライブラリを使用したタイマ割り込みを実装することができました。これでプログラミングの幅が広がると思います。
次回は、APIを使用しないでFlashにデータを書き込み、読み込みの実装について書いていこうと思います。