TIM Iインプットキャプチャの使い方(NVIC / DMA)


TIM2 のインプットキャプチャを使用してみます。 ここでは周期やパルスのLow時間の計測を行ってみます。

1. STM32L010 TIM2 Input Capture / 周期計測・割込み

周期測定の場合、下図のようにTIM2_CH1の立下りでキャプチャすることで計測できます。
今回は波形ではなくキー入力とします。


1.1. TIM2の設定

TIM2 CH1を入力として設定します。
入力がキーなので、Parameter Settings はわかりやすいように Prescalerを31999としてクロックを1msとします。
Polarity SelectionはFalling Edgeに設定します。
割込みも有効にしておきます。
また、PA0はPullUpに設定しておきます。


















1.2. コーディング

HAL_TIM_IC_Start_IT関数でTIM2が起動します。
割込みコールバック関数はHAL_TIM_IC_CaptureCallbackです。
/* USER CODE BEGIN PV */
volatile uint16_t	g_usCC1 = 0;
volatile uint16_t	g_usCC2 = 0;
volatile uint16_t	g_usFlag = 0;

/* USER CODE END PV */
				
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	g_usCC1		= g_usCC2;
	g_usCC2		= __HAL_TIM_GET_COMPARE(htim,TIM_CHANNEL_1);
	g_usFlag	= 1;
}
/* USER CODE END PV */
				
g_usCC1は最新のCC1レジスタ値。
g_usCC2は前回のCC1レジスタ値。
g_usFlagはg_usCC1、g_usCC2を更新したフラグ変数です。
  /* USER CODE BEGIN 2 */
  HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
  /* USER CODE END 2 */
  				
HAL_TIM_IC_Start_IT関数でTIM2を起動します。
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  if (g_usFlag != 0) {
		  g_usFlag = 0;
		  sprintf(msg, "%05dms (%04X/%04X)\r", g_usCC2 - g_usCC1, g_usCC2, g_usCC1);
		  UsartTransmitStrings(&huart2, msg);
	  }
  }
  /* USER CODE END 3 */
				
周期はg_usCC1とg_usCC2の差で求まります。


2. TIM2 Input Capture / Low時間計測・割込み

Low時間測定の場合、下図のようにTIM2_CH1の立下りと立ち上がりでキャプチャすることで計測できます。


2.1. TIM2の設定

TIM2 CH2を入力として設定します。
Channel2はInput Capture indirect modeに設定します。
Input Capture direct modeにするとPA1がTIM2_CH2として設定されてしまいます。
Input Capture Channel 2Polarity SelectionRising Edge にします。




2.2. コーディング

割込み処理を以下の様に変更します。
	if ((*htim).Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
		g_usCC1 = __HAL_TIM_GET_COMPARE(htim,TIM_CHANNEL_1);
	}

	if ((*htim).Channel == HAL_TIM_ACTIVE_CHANNEL_2) {
		g_usCC2 = __HAL_TIM_GET_COMPARE(htim,TIM_CHANNEL_2);
		g_usFlag = 1;
	}
				
g_usCC1は最新のCC1レジスタ値。
g_usCC2は最新のCC2レジスタ値。
g_usFlagはg_usCC2を更新したフラグ変数です。
Low時間はg_usCC1とg_usCC2の差で求まります。
  /* USER CODE BEGIN 2 */
  HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
  HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);
  /* USER CODE END 2 */
  				
HAL_TIM_IC_Start_IT関数でTIM2 Channel2を起動します。


3. TIM2 Input Capture / Low時間計測・DMA)

次に割込みからDMAに変更します。

2.1. TIM2の設定

DMAを設定します。
TIM2_CH1とTIM2_CH2を設定し、ModeCircularIncrement Addressはチェックを外します。
TIM2割込みはチェックを外します。




3.2. コーディング

割込み処理を以下の様に変更します。
/* USER CODE BEGIN 0 */
void HAL_TIM_IC_CaptureHalfCpltCallback(TIM_HandleTypeDef *htim)
{
	if ((*htim).Channel == HAL_TIM_ACTIVE_CHANNEL_2)
		g_usFlag = 1;
}
/* USER CODE END 0 */
				
DMA転送終了割込みコールバック関数はHAL_TIM_IC_CaptureHalfCpltCallbackになります。
引数TIM_HandleTypeDef *htimでDMA転送終了Channelを判別できます。
今回はCC2のDMA転送終了で処理します。
  /* USER CODE BEGIN 2 */
  HAL_TIM_IC_Start_DMA(&htim2, TIM_CHANNEL_1, (uint32_t *)&g_usCC1, 1);
  HAL_TIM_IC_Start_DMA(&htim2, TIM_CHANNEL_2, (uint32_t *)&g_usCC2, 1);
  /* USER CODE END 2 */
  				
HAL_TIM_IC_Start_DMA関数でTIM2 Channel/2を起動します。
CH1はg_usCC1、CH2はg_usCC2にDMA転送するよう指定します。


以下は今回の回路図です。