STM32L010 TIMの使い方(PWM)


TIM2を使用し1ms 周期のPWMを作成します。

1. デバイスの設定

1.1. TIM2の設定

Timers内TIM2を選択し、Mode を以下の様に設定します。
Clock Source Internal Clock
Channel1 PWM Generation CH1








Parameter Settingsを以下の様に設定します。
Prescaler 31
Counter Mode Up
Counter Period (AuroReload Register - 16bit value 999
上記設定でPWMの周期を決めます。
system clock = 32MHzなので、Prescalerで1/32としてTIM2のクロックソースを1MHzに設定。
Counter Periodを1000カウントとすることで周期を1msとします。
Prescalerへの設定値は分周値-1とします。
Counter Periodの設定値も-1した値とします。




1.2. 割込みの設定

NVIC Interrupt Tableを選択しEnabledにチェックを入れます。
その後、Code Generateを実行。




2. コーディング

2.1. TIM2割込み処理

USER CODE BEGIN PVの下に外部変数を追加します。
ここでは uint32_t g_uwDutyとします。
/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim2;

/* USER CODE BEGIN PV */
uint32_t	g_uwDuty=0;

/* USER CODE END PV */
				
USER CODE BEGIN 2の下に。HAL_TIM_PWM_Start_ITを記述します。
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_1);

  /* USER CODE END 2 */
				
USER CODE BEGIN 4の下に割込み処理関数を記述します。
関数名はHAL_TIM_PWM_PulseFinishedCallback固定です。
g_uwDuty を変化させ、10%ステップでDuty Cycleを変更します。
/* USER CODE BEGIN 4 */
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
	g_uwDuty += 100;
	__HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_1, (g_uwDuty - 1) % 1000);
}

/* USER CODE END 4 */
				
コーディングはここまでです。



3. 動作確認

実行すると以下のような波形が発生します。




次にPWMのDuty比を最大・最小値で交互に切り替えてみましょう。
計測しやすいようにCounter Periodを15に設定します。
次にHAL_TIM_PWM_PulseFinishedCallbackを以下の様に変更します。

/* USER CODE BEGIN 4 */
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
//	g_uwDuty += 100;
//	__HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_1, (g_uwDuty - 1) % 1000);

	g_uwDuty++;
	__HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_1, g_uwDuty & 1 ? 1 : 14);
}

/* USER CODE END 4 */
				
実行すると以下のような波形が発生します。
正しく動作しないことがわかります。


ここで割込み種別を変更します。
割込みをCC1からUPDATEに変更します。
  /* USER CODE BEGIN 2 */
  HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_1);
  __HAL_TIM_DISABLE_IT(&htim2, TIM_IT_CC1);
  __HAL_TIM_ENABLE_IT(&htim2, TIM_IT_UPDATE);

  /* USER CODE END 2 */
				
HAL_TIM_PeriodElapsedCallbackを追加し、以下の様に変更します。
/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	g_uwDuty++;
	__HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_1, g_uwDuty & 1 ? 1 : 14);
}

/* USER CODE END 4 */
				
実行すると以下のような波形が発生します。
正しく動作していることがわかります。


PWMで割込みを使用する場合はTIM_IT_UPDATEを使用したほうが良いかもしれません。