回路の動作確認ができたので、ここからマイクロマウスプログラムの準備に入ります。次は定期割り込み処理を行います。LEDでチカチカするようにしてみます。
参考URLです。
タイマー
割り込みに使うタイマーをどれにするか、改めてSTM32F446のデートシートから見てみます。
画像引用:STM32F446データシート
ざっくり3種類あります。
- 高度な制御:TIM1、TIM8
- 汎用:TIM2~5、9~14
- 基本:TIM6,、TIM7
それぞれ、説明文を見てみます。
Advanced-control timers
画像引用:STM32F446データシート
要約すると、ブラシレスモータの制御に使う相補PWM出力可能な3相PWMジェネレータが搭載されていたり、汎用タイマーとしても使えたり、他のタイマーとも連携して使えるとのこと。
General-purpose timers
画像引用:STM32F446データシート
汎用タイマーです。自動リロードアップ/ダウンカウンターを持っていたり、入力キャプチャや、出力比較、PWMを生成したり、1パルスモード出力?ができるとあります。
TIM2、TIM3、TIM4、TIM5は、インクリメンタルエンコーダ信号と1〜4個のホール効果センサーからのデジタル出力を処理できるとのこと。
TIM9、TIM10、TIM11、TIM12、TIM13、TIM14は、単純なタイムベースとしても使用できます。
Basic timers
画像引用:STM32F446データシート
TIM6、TIM7は、主にDACトリガーと波形生成に使用されます。これらは、一般的な16ビットタイムベースとしても使用できます。
TIM2はモータドライバ入力用のPWMで使用しており、TIM3、TIM4はエンコーダカウント用で使用済み。TIM6 or TIM7はDACで使用予定なので、汎用タイマーのTIM10、TIM11を使ってみようと思います。
STM32CubeMX
クロック設定とLED設定は過去にやっているのをそのままやります。
TIM10の設定です。Activatedにチェックを入れて、PrescalerとCounter Periodに割り込み周期を決めるための数値を入れていきます。以下はTIM10の設定の画像。
ここで、PrescalerとCounter Periodの値の決め方ですが、PWMの設定のときと同じように、もととなる入力クロックを調べる必要があります。ブロック図をみます。
画像引用:STM32F446データシート
TIMER10とTIMER11は、AHB/APB2につながっています。
CubeMXのClock Configurationの周波数を見てみます。
APB2 timer clocks(MHz)は180になっています。TIM10とTIM11は、このクロックが元になります。
マイクロマウスの制御周期である1kHzの割り込みをしたいときの計算式は、以下のようになります。PWMのときと同様です。
割り込み周波数 = クロック周波数 / ((Prescaler + 1) * (Counter Period + 1))
1kHz = 180MHz / ((Prescaler + 1) * (Counter Period + 1))
Counter Period = 180-1
Prescaler = 1000 – 1
1kHzで割り込みを行いたいときは、Counter Period = 179、Prescaler = 999を入れることになります。
今回はLEDで点滅させたいので、人の目に見える範囲まで割り込み周期を落としてみます。
なので、TIM10は10Hz、TIM11は1Hzにしてみます。16bitカウントなので、入力する数値は65535以下になるようにします。
10Hz = 180MHz / ((Prescaler + 1) * (Counter Period + 1))
Counter Period = 1800-1
Prescaler = 10000 – 1
1Hz = 180MHz / ((Prescaler + 1) * (Counter Period + 1))
Counter Period = 18000-1
Prescaler = 10000 – 1
TIM10のときは、以下のように入力します。
TIM11のときは、以下のように入力します。
NVIC Settingsのglobal interruptにEnabledチェックを入れます。これで割り込みとなります。
TIM10の画面。
TIM11の画面。
これでCubeMXの設定は完了です。
プログラム
今回使うHAL関数です。タイマースタート関数と、割り込みコールバック関数になります。
画像引用: Description of STM32F4 HAL and low-layer drivers
画像引用: Description of STM32F4 HAL and low-layer drivers
それぞれTIM*を指定するだけのようです。
/* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim == &htim10){ HAL_GPIO_TogglePin(D1_GPIO_Port, D1_Pin); } if (htim == &htim11){ HAL_GPIO_TogglePin(D2_GPIO_Port, D2_Pin); } } /* USER CODE END 0 */
/* USER CODE BEGIN 2 */ HAL_TIM_Base_Start_IT(&htim10); HAL_TIM_Base_Start_IT(&htim11); /* USER CODE END 2 */
割り込みなので、while文には何も記述しません。
実行
実行してみます。割り込みで点滅なので周期はそれぞれ20Hz(0.1秒点灯0.1秒消灯)、2Hz(1秒点灯1秒消灯)になっています。
そのままHAL_TIM_PeriodElapsedCallback関数に記述していけばいいのかわかっていないため、おいおい改定するかもしれません。