皆さま こんにちは。
今回は LL を使ってPWM出力してみます。
LLってな~に?という方は HALとLL の記事をご覧ください。
投稿時の開発環境を記しておきます。
PC:Windows10 OS
IDE: STM32CubeIDE Version1.5.0
Configurator: STM32CubeMX Version6.1.0
Board: STM32Nucleo-F401RE
PWMとは?
PWMとは、Pulse Width Modulation の略です。日本語ではパルス幅変調といいます。
I/Oポートからパルスを出力する機能です。
パルス幅を変えることでモーターを制御したり、LEDの明るさ調節を行ったりすることができます。
今回はボードに載っている緑色のLED(LD2)がたまたまPWM出力ポートにつながっているので、それを使ってみます。
プロジェクトを作成する
IDEを起動し、File- New – STM32 Project を選択し、Target Selection ウィンドウが出たら Board Selector タブを選択し Boards List から NUCLEO-F401RE を選択し Next ボタンを押します。
Project 名に F401PwmLL と入力し、Finishボタンを押します。
Initialize all peripherals with their default Mode ? と聞いてくるので Yesを押します。
UARTをLLで使う準備をする
Project Managerタブを選択し Advanced Settings を見ると TIM の項目がありません。
そこでまず Pinout & Configuration で端子の設定を行ってみます。
マイコンの図を見てください。
今回設定をする端子は下側の PA5 です。
PA5を右クリックし、リストから TIM2_CH1 を選択すると端子が黄色にかわります。
そして Pinout & Configuration – Categories – Timers – TIM2 を選択し、
TIM2 Mode and Configuration – Mode – Channel1 のリストから PWM Generation CH1 を選択します。
端子が黄色から緑色にかわりました。
TIM2 Mode and Configuration – Configuration – Parameter Settings を以下のように設定します。
TIMをLLで使う準備をする
ここまで設定してあげると TIM で LL が使えるようになります。
Project Managerタブを選択し Advanced Settings の TIM を HAL (初期値)から LL に変更します。(コンボボックスで選択する)
HALの部分をクリックするとコンボボックスのリストが表示されるので、LLを選択します。
Clock Configurationタブをクリックして見ると HCLK が 84MHz であることがわかります。
HCLK が 84MHz なので
84MHz / ((83 + 1) * (999 + 1)) = 84 * 10^6 Hz / (84 * 10^3) = 10^3 Hz = 1 kHz
この設定で周期が 1kHz の PWM出力になります。
Project Explorer で F401PwmLL を選択し、Project – Build Project でビルドします。
コードを追加する
main()の while()ループの部分を以下の通りにコーディングします。
/* USER CODE BEGIN WHILE */
LL_TIM_EnableCounter(TIM2);
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH1);
while (1)
{
LL_TIM_OC_SetCompareCH1(TIM2, 999);
HAL_Delay(1000);
LL_TIM_OC_SetCompareCH1(TIM2, 500);
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
ビルドして実行する
ビルドしてエラーがないことを確認してプログラムを実行します。
Run – Resume
緑色のLEDが明るくなったり暗くなったりすれば成功です。
確認のためにオシロスコープで波形を観測してみました。
周波数は約 1kHz になっていることが確認できました。
コードの概要
LL_TIM_EnableCounter(TIM2)と
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH1) でPWM出力を開始します。
__HAL_TIM_SET_COMPARE はレジスタ CCR の値を変更するマクロです。
LL_TIM_OC_SetCompareCH1(TIM2, 250);
で TIM2 , CH1 のデューティ比を変えることができます。
第3引数の値が 500 でデューティ比が 50% になりました。(上の波形の左側の部分)
250 の時に H レベルの期間が 1/4 になっています。(上の波形の右側の部分)
パルス幅変調(PWM)モードでは、TIMx_ARR レジスタの値によって決められた周波数と TIMx_CCRx
レジスタの値によって決められたデューティサイクルで信号を生成できます。
設定画面の Counter Period ( == 999 ) が TIM2_ARR の値になります。
アップカウンタでは1カウント目が0になる仕様なので、分母は 1000 です。
PWM出力の信号がLEDのアノードにつながっているので、__HAL_TIM_SET_COMPARE()の第3引数の値を n とすると
n / 1000 の期間だけ LED が点灯することになります。( n が TIM2_CCRx の値 です )
PWMに関しては HAL と LL でRAMの使用量もコード量も大差はないようです。
ビルドアナライザーで確認したRAMとFlashの消費量(単位[KB])は以下のとおりです。
通信制御と違って設定値をレジスタに書く程度なので、さほど差は出ませんでした。
これなら、どちらを使っても良さそうですね。
ライブラリ | RAM | Flash |
---|---|---|
HAL | 1.67 | 10.17 |
LL | 1.61 | 10.93 |
さていかがでしたか、皆さまはうまく PWM 出力できましたか?
お疲れさまでした。