본문 바로가기
DSP, MCU/STM32 (ARM Cortex-M)

STM32 ] Timer Input Capture 사용하여 PWM 신호 캡쳐하기

by eteo 2022. 7. 25.

 

 

먼저 클락 설정

 

 

 

 

 

 

 

 

PWM 파형을 만들어 내기 위한 TIM1 설정

 

TIM1은 APB2에서 클락소스를 공급받는다.

 

PSC와 ARR의 값을 위와 같이 설정해서 Frequency 를 50Hz로 맞춰줬다. 펄스폭은 소스코드 상에서 수정할거라 안건드렸다.

 

 

 

 

인풋캡처를 위한 TIM2 설정

 

 

 

TIM2은 APB1에서 클락소스를 공급받는다.

PSC를 90-1로 해서 1us 업카운터로 설정한다. 인풋캡처 채널은 하나는 Rising Edge 하나는 Falling Edge로 설정한다.

 

 

 

TIM2의 인터럽트 켜기

 

 

 

 

소스코드

/* USER CODE BEGIN PV */
int __io_putchar(int ch){
	HAL_UART_Transmit(&huart3, &ch, 1, 1000);
    return ch;
}
/* USER CODE END PV */

...

/* USER CODE BEGIN 0 */
uint32_t IC_Val1 = 0;
uint32_t IC_Val2 = 0;

float frequency = 0;
float dutyCycle = 0;

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{

	if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)  // if the interrupt source is channel1
	{
		IC_Val1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
		TIM2->CNT = 0;
	}
	if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)  // if the interrupt source is channel1
	{
		IC_Val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
		dutyCycle = (float)IC_Val2/(float)IC_Val1 * 100;
		frequency = 1000000 / (float)IC_Val1;
	}

}
/* USER CODE END 0 */

...

  /* USER CODE BEGIN 2 */

  TIM1->CCR1 = 125;
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
  HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
  HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  printf("Period: %.2fms, PulseWidth: %.2fms, DutyCycle: %.2f%%, Frequency: %.2fHz\r\n"
			  , (float)IC_Val1/1000, (float)IC_Val2/1000, dutyCycle, frequency);
	  HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

 

먼저 while문 위에서 TIM1의 CCR1 값을 125로 세팅해서 듀티비를 125/1000*100=12.5%로 맞춰줬다. 각자 PWM 과 IC 채널 1,2 인터럽트를 스타트한다.

 

인풋캡쳐 콜백함수 내에서 DutyCycle과 Frequency를 측정한뒤 while문 안에서 출력하는데 IC_Val1과 IC_Val2는 us 단위에서 ms 단위로 바꿔서 출력한다.