こんにちは、しゅうです。
最近寒いですね、残暑というものはいったいどこに行ったのやら。
今回は割り込み処理を実装していきます。
割り込み?
プログラムは基本的にmain関数などに書かれている動作を上から順番に実行します。ここで、プログラムが長くなると、最初に行ったセンサ値の更新などをもう一度行うまで時間がかかってしまったり、安定して行うことができなくなってしまいます。
そこで、割り込み処理という、main関数の実行とは別で行われる処理をさせます。これにより、予め設定した処理(センサ値の更新など)を一定の周期で行いつつ、main関数の実行が行えます。(下記図を参考にしてください)
設定
引き続きMotorプロジェクトの中で作業を続けます。前回の記事で述べたように、TIM4を割り込み用に設定します。次の画像のように、TIM4を有効化するためにInternal Clockのところにチェックを入れましょう。
次に周期などの設定を行います。以前、PWMを設定した時(参考記事)と同じように1kHzで設定します。すなわち、Prescalerを32-1、Counter Periodを1000-1に設定します。
そして、PWMの時と違ってもう1つ設定するものがあります。Configuration画面のNVIC Settingsに行き、TIM4 global interruptを有効化します。これで割り込み処理を行うことができます。
ここまできたら、プログラムを出力して次に進みましょう。
割り込み用のプログラム
今回はmain.cだけでなく、stm32f1xx_it.cというプログラムも編集します。このプログラムの最後の方に、TIM4_IRQHandler関数が定義されています。これは、先ほど設定したTIM4 global interruptを有効化したためです。以下のコードが、出力時の状態です。
void TIM4_IRQHandler(void) { /* USER CODE BEGIN TIM4_IRQn 0 */ /* USER CODE END TIM4_IRQn 0 */ HAL_TIM_IRQHandler(&htim4); /* USER CODE BEGIN TIM4_IRQn 1 */ /* USER CODE END TIM4_IRQn 1 */ }
ここに、以前main関数で使っていたエンコーダの表示処理を追加します。
printf("Checking encoder... \n\r"); count += read_encoder(); // Reading the encoder's value printf("Counted: %d\n\r",count); // Display count value
また、stm32f1xx_it.cの最初に、
- stdio.hライブライをインクルード
- UART用の変数定義(huart2)
- __io_putcharとread_encoder関数のプロトタイプ宣言
を忘れないようにしましょう。さらに、main関数の方でも、エンコーダ処理のコメントアウトや関連する変数定義のコメントアウトも忘れないようにしましょう。printfも全てコメントアウトした方がわかりやすいですね。
それではビルドして書き込みを行いましょう。
実行
モータは以前と同様、1秒回転して1秒停止します。こちらの記事で解説したscreenコマンドを実行すると、下の画像のような実行結果が表示されてました。
いや何も表示されませんね…?
原因調査
しばらく考えた結果、もしかしたらエンコーダと同じように割り込みを開始するための関数があるのでは?と思い調べてみました。
ビンゴ!!以下の関数を、stm32f1xx_hal_tim.cの中で見つけました。
HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)
こちらの関数を、TIM4の初期化関数のstatic void MX_TIM4_Init(void)で呼び出すと良さそうですね。僕の場合はmain.cの310行目付近にありました。
実行part2
さぁ気を取り直してビルドと書き込みを行いましょう!
無事表示に成功しました〜!モータも想定通り、1秒ごとに回転と停止を繰り返してくれました。
まとめ
ということでなんとか割り込み処理の実装ができました。
ただし、1kHzで割り込みをしているのか?という疑問はあります。
もう少し精査しないと行けなさそうですね…
ひとまず今回は以上!それでは〜