STM32マイコン「STM32F303K8T6」を動かす(タイマーを使う)

前回の記事では、秋月電子で購入できる「STM32F303K8T6」を使ってLチカしてみました。周辺機能を使うためのメモを備忘録として残しておきます。

STM32マイコン STM32F303K8T6: 半導体 秋月電子通商-電子部品・ネット通販
電子部品,通販,販売,半導体,IC,LED,マイコン,電子工作STM32マイコン STM32F303K8T6秋月電子通商 電子部品通信販売

タイマー

STM32F303K8T6のタイマー構成

STM32F303K8T6以下の汎用タイマーが搭載されています。用途に合わせて使い分けが必要です。
Advanced timer (TIM1)
General-purpose timers (TIM2, TIM3, TIM15, TIM16, TIM17)
Basic timers (TIM6 and TIM7)

Advanced timerやGeneral-purpose timerは汎用的に使うことのできる高機能タイマーです。PWMの生成などに用いることが可能です。もちろんタイマー割り込みやADC,DACトリガ用途としても用いることができます。Basic timerは先のタイマーよりも単機能なタイマーになります。タイマー割り込み、ADC,DACトリガなど単純な制御に用いられます。

この汎用タイマーのほかに「STM32F303K8T6」には 以下のタイマーも搭載されています。
Watchdog timer 2ch
SysTick timer 1ch (CPU用の簡単なタイマー RTORなどで用いる)

Watchdog timerはマイコンのプログラムが暴走したり、どこかで停止していないかを監視するためのタイマーです。プログラムの異常時に停止または、CPUリセットをかけるような使い方ができます。SysTick timerはCPUが持つシンプルなタイマーです。ROSの基本タイマとして用いる他、CPUの処理速度を計測したりと簡単なタイミングを計る場合に便利なタイマーです。

タイマー 割り込み

最も基本的な割込み動作のタイマー割り込みを実装してみます。
タイマー割り込み用としてはBasic timer(TIM6 and TIM7)を用いることが多いようです。他の高機能タイマーを周期的なタイマー割り込みだけに利用するのは少しもったいない気もしますね。

CubeMXでの設定
今回は、TMI6をタイマー割り込みに利用します。

「Count up」
「Prescaler」= 0 (64MHzをカウンタークロックに設定)
「Counter Period」=1279 (1280- 1 を設定)

64[MHz] / 1280 = 50[kHz]周期でタイマー割り込みが発生します。

自動生成されたTIM6設定、初期化のための関数です。

//*****************************************************************************
// TIM6 Initialization Function
//*****************************************************************************
static void MX_TIM6_Init(void)
{

	/* USER CODE BEGIN TIM6_Init 0 */

	/* USER CODE END TIM6_Init 0 */

	TIM_MasterConfigTypeDef sMasterConfig = {0};

	/* USER CODE BEGIN TIM6_Init 1 */

	/* USER CODE END TIM6_Init 1 */
	htim6.Instance = TIM6;
	htim6.Init.Prescaler = 0;
	htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
	htim6.Init.Period = 1279;
	htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
	if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
	{
		Error_Handler();
	}
	sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
	sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
	if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
	{
		Error_Handler();
	}
	/* USER CODE BEGIN TIM6_Init 2 */

	/* USER CODE END TIM6_Init 2 */
}

ここで割込み周期を設定します。

htim6.Init.Period = 1279;

割り込み発生時に以下のタイマー割込み用ハンドラ関数が呼ばれ処理されます。関数内でhtim6ハンドラをチェックしてTMI6による割り込みが発生した時にGPIOへのデータ出力を反転します。これで割り込み処理によるLチカが実装できました。

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    static short Led = 1;

    if (htim == &htim6){
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, Led);
        Led = 1 - Led;
    }
}

PWM

タイマーを使ってPWMを生成してみます。
PWM生成用としては General-purpose timer(TIM2, TIM3, TIM15, TIM16, TIM17)を用いることが多いようです。このタイマーは、Basic timersと比較すると機能が多くなっているため必然的に設定する項目も多くなります。

CubeMXでの設定
今回は、TMI2をPWM生成に利用します。周期は100kHzとします。
「Count up」
「Prescaler」= 0 (60MHzをカウンタークロックに設定)
「Counter Period」=599 (600- 1 を設定)

60[MHz] / 600 = 100[kHz]周期でタイマーPWMが発生します。

自動生成されたTIM2設定、初期化のための関数です。

static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 0;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 599;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  __HAL_TIM_DISABLE_OCxPRELOAD(&htim2, TIM_CHANNEL_1);
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */
  HAL_TIM_MspPostInit(&htim2);

}

PWMのパルス幅を設定するAPI

__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 300);

※2025年11月
記事を公開するのを忘れていました。それにしても「STM32F303K8T6」高くなってしまったなぁ…..ということで最近はRaspberry Pi Picoを使うことが多くなってしまいましたがせっかくまとめてあったので一旦公開しておきます。

コメント