LoginSignup
11
15

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-03-08

はじめに

なんとなく相補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

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

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

11
15
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
15