STMicroelectronics社純正開発環境Cube IDEを使用し、STM32のHAL(ハードウエア抽象化レイヤ)を思いつくまま試用中。前回はメモリ間でDMA転送。続いてDACとメモリ間の転送をすべしと思いきや、そのためにはタイマを使わないといけません。そういえばタイマを練習していなかった。今回はタイマね。
※Windows 11 PC上にインストールしたSTM32CubeIDE Version: 1.13.2上で動作を確認しています。今回のターゲットボードは Nucleo-F072RBです。
STM32F072RBのTIMER群
流石です。STM32F072RBはSTM32の中では「お求めやすい」価格帯の機種だと思うのですが、なんと12本もタイマを搭載しています。12本の中にはWatchDogとかも含まれているので、所謂「汎用タイマ」として使えるタイマは9本ですが、それでも充実のラインナップ。
前述のようにメモリとDAC間のDMA転送時のトリガに使用したいので「インターバル・タイマ」として動いてくれれば十分。インプット・キャプチャとかアウトプット・コンペアとか入出力機能は特に必要ありません。
そういう観点で眺めると、以下のタイマは単なるインターバルタイマとして用いるのはもったいないです。そして調べてみたらば、DMAのリクエスト信号を生成するタイマとしては使えないのでした。
-
- TIM1、唯一の「アドバンスド」タイマ、キャプチャ、コンペア関係のIO制御機能が充実。16ビット・カウンタ。
- TIM2、唯一の32ビット・カウンタ装備。やはりIO機能充実。
- TIM3、IO機能充実。16ビット・カウンタ。
- TIM14、IO機能あり。16ビット・カウンタ。
結局DMAリクエストのために使用可能なのは以下の5本です。
-
- TIM15、IO機能あり。16ビット・カウンタ。
- TIM16、IO機能あり。16ビット・カウンタ。
- TIM17、IO機能あり。16ビット・カウンタ。
- TIM6、IO機能無。16ビット・カウンタ。
- TIM7、IO機能無。16ビット・カウンタ。
やはりIO機能があるTIM15、16、17はモッタイナイので今回は「ベーシック」タイマTIM6を使用してみることにいたしました。どうもTIM6は、DMAのリクエスト用に期待されている?感じです。
なおTIMERの番号が飛び飛びなのは同じタイマ番号であれば、他のSTM32マイコンでも同じように動くことが期待できるたようになっているためのようです。ユーザーに優しいナンバリング?今回TIM6を練習したらば、別機種でもいける筈。
今回のTIM6の使用方法
今回はTIM6のHALの練習ということで、以下のようにしてみました。
-
- TIM6はインターバル・タイマとして定周期で動かす
- TIM6の「定周期」で割り込みを発生させる
- 割り込みルーチン内でPA9端子をトグルさせる
今回は割り込みですが、これをDMAリクエストに置き換えればDMAを駆動できる筈。割り込み周期は目標10kHzとしてみました。なお、PA9端子は、Arduino互換ピンソケットのD8端子です。D8端子を見張れば(トグルなので)5kHzの信号が観察できる筈。
CubeIDEでのセッティング
まずは肝心のTIMERのセッティングより。Timers欄にタイマがぎょうさん列挙されとります。
システムクロックはデフォルトのまま 48MHzなので、4800カウント設定により10kHz周期になる筈(あれ、4799であるべきか?1多いかも。。。)
最後にPinの設定。PA5は「いつものLチカ」用のユーザーLED、PC13はユーザーボタンです。
上記設定でソースをGenerate。
実験に使用したソース
自動生成のソースに手を入れたところが以下に。Cube IDEのお作法により、自動生成されたソース内の「User書き変え可」部分に書き込んだところのみ列挙してます。まずは main.c から。
タイマ割り込みハンドラと「共有する」変数をことさらに一個作っておきました。
/* USER CODE BEGIN PV */ volatile int pa9flag; /* USER CODE END PV */
タイマの初期化後にタイマをスタートさせるところが以下に。
/* USER CODE BEGIN 2 */ HAL_TIM_Base_Start_IT(&htim6); pa9flag = 0; /* USER CODE END 2 */
メイン関数のループ内の吉例Lチカ部分です。ここはタイマと関係なくCPUが動いておるぞというオシルシのため。
/* USER CODE BEGIN 3 */ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); HAL_Delay(200); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); HAL_Delay(200); } /* USER CODE END 3 */
さて割り込みハンドラ側です。ファイル名はstm32f0xx_it.c。その中の関数
void TIM6_DAC_IRQHandler(void)
です。これは自動生成のファイル名で、最初からTIM6はDACと「握る」ことをST社の中の人も期待している?お名前かと。
/* USER CODE BEGIN TIM6_DAC_IRQn 0 */ if (pa9flag == 1) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET); pa9flag = 0; } else { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET); pa9flag = 1; } /* USER CODE END TIM6_DAC_IRQn 0 */
上記はピンをトグルさせる関数を使えばもっとスッキリできる筈だけれど、まあいいか、後でハンドラに指令を出さないといけないかも知れないし。
実機上での実行
コマケーことを言わなければ予定通りか。