Edited at

STM32F303k8+HALで相補PWM生成を試した

More than 1 year has passed since last update.


はじめに

なんとなく相補PWM(Complementary PWM)を生成したい気分だったのでやってみました.

手探りでやったため色々と不適切な点があるかと思います.

その時は指摘していただければ修正いたします.


内容


  • CubeMXでの設定

  • 生成されたプログラムへの追加点


CubeMxでの設定

まず,303k8用にprojectを作成します.

今回はnucleo-303k8を使っていきます.

初期状態はこんな感じです。

first.png


pinoutタブ

ツリーのPeripheralsからTIM1を展開し,Channel1の設定を

PWM Generation CH1 CH1N

にします.

すると,

18pin → TIM1_CH1

13pin → TIM1_CH1N

と設定されます。

second.png

注意してほしい点として,303k8では相補PWMはAdvanced timerであるTIM1しか使えません.

TIM2やTIM3などのGeneral-purpose timerでは相補PWMはサポートされていないので気を付けましょう.

[3/10追記]

TIM15,16,17にも相補のチャンネルがあるっぽいですが、これらはまだ試してないです.


configurationタブ

ピンの設定が完了後,configurationタブに移動し,TIM1の各値を設定していきます.

third.png

値を設定するタブは

- Counter Settings

- PWM Generation Channel 1 and 1N

の2つです.

まずCounter SettingsタブでPWMの周波数を設定します.

今回は20kHzでPWMを出力するようにPrescalerとCounter Periodを決めます。

動作クロックは内部の8MHzを使うので

Prescaler:0

Counter Period:400-1

(カウントは0からなので1引いた399を設定する)

とします.

PWM Generation Channel 1 and 1Nタブでは

Mode: Assymetric PWM1

とします.

[3/9追記]

デッドタイムの設定もCubeMxでできます.

Break And Dead Time managementタブの一番下の欄に

Dead Time:10(0-255で任意の値)

と設定します.


CubeMx側で設定すればコード再生成時等に楽です.

無題.png

ここまで設定したら,コードを生成します.

fourth.png


プログラムへの追加

コードは量が多いうえに見づらいので後ほどGithub等に上げます.

[3/10追記]

こちらに上がっています。Src/main.cが本体です。

今回は変えたポイントと追加した関数について解説します.


変更点

[3/9追記]

上記の通りCubeMx側で設定してしまった方がコード再生成等の時に楽です。


変えるポイントは,MX_TIM1_Init関数内の一か所です


change_point

static void MX_TIM1_Init()

{
......
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 10;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.BreakFilter = 0;
sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
sBreakDeadTimeConfig.Break2Filter = 0;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
}

sBreakDeadTimeConfig.DeadTime = 10;

ここでデッドタイムを設定します.

値は8bitで0-255の間です.今回はとりあえず10とします.



user関数の追加

また,PWMを扱いやすくするために以下の関数を定義します.

プロトタイプ宣言は適宜お願いします.


user_function

void user_tim1_pwm_setvalue(float value)

{
TIM_OC_InitTypeDef sConfigOC;
sConfigOC.OCMode = TIM_OCMODE_ASSYMETRIC_PWM1;
sConfigOC.Pulse = (uint32_t)((400)*value);
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
}

この関数が相補で出力する際のポイントとなります.

出力する値を決めます.

sConfigOC.Pulse = (uint32_t)((400)*value);

設定値を反映します.

HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);

CH1へ出力します.

HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);

CH1Nへ出力します.

HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);

一番最後のHAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);がないと,CH1Nからは出力されません.

できたらビルドして書き込んで動かしてオシロで見ると以下のような波形が得られると思います.

image

やり方はとりあえず以上です.

よくわからないこと,質問等あったらよろしくお願いします.