PWM出力で1サイクルごとにデューティー比を更新していくのに、割込みで処理していると厳しいため、DMAを使うことにした。
Cube MXの方での設定は省略。
DMAの動作を開始するには、HAL_TIM_PWM_Start_DMAを使う方法と、HAL_DMA_Start_ITを使う方法がある。
位置付けとしてはHAL_DMA_Start_ITの方が下位で、HAL_TIM_PWM_Start_DMAでは中でHAL_DMA_Start_ITを呼んでいる。
その他に、タイマ側の開始なども合わせて実行してくれる。
HAL_DMA_Start_ITを使う場合は、タイマ側は別途自分で処理を実行しなければならない。
HAL_DMA_Start_ITでDMAを開始した後、__HAL_TIM_ENABLE_DMAで該当するチャンネルのDMAを有効にして、HAL_TIM_PWM_StartでPWM出力を開始する。
今回はこちらの方法を使った。
DMAはCircularモードで、リングバッファから読み出して自動的にPWMの設定を更新する。読み出しのタイミングに合わせて、外部からリングバッファに新しいデータを書き込んでいけばよい。
この読み出しのタイミングを見るのに、当初はDMAの割込みを使った。XferCpltCallbackとXferHalfCpltCallbackで、読み出し位置のフラグをセットする形である。
しかし調べてみると、__HAL_DMA_GET_COUNTERというのがあって、直接読み出し位置を取得できることがわかった。わかりやすいし、余計な割込みも発生しないので、こちらを使う処理に変更した。