cancel
Showing results for 
Search instead for 
Did you mean: 

stm32g0 timer input capture division does not work

Bigdan
Associate III

Hello!

Using TIM1 for pwm input capture.

Works OK for trigger prescaler 1 (default).

Want to use prescaler 4, but it doesn't work. Capture value the same as prescaler 1.

 

Timer config:

void FC_SERVO_1_TIM1_Init(void)
{

	// USER CODE END TIM1_MspInit
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	/* TIM1 clock enable */
	__HAL_RCC_TIM1_CLK_ENABLE();
	__HAL_RCC_GPIOA_CLK_ENABLE();
	/**TIM1 GPIO Configuration
	PA8     ------> TIM1_CH1
	*/
	GPIO_InitStruct.Pin = GPIO_PIN_8;
	GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	GPIO_InitStruct.Alternate = GPIO_AF2_TIM1;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

	/* TIM1 interrupt Init */
	HAL_NVIC_SetPriority(TIM1_CC_IRQn, 0, 0);
	HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);
  // --------------------

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_SlaveConfigTypeDef sSlaveConfig = {0};
  TIM_IC_InitTypeDef sConfigIC = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM1_Init 1 */

  /* USER CODE END TIM1_Init 1 */
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 15;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 65535;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  {
	Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
  {
	Error_Handler();
  }
  if (HAL_TIM_IC_Init(&htim1) != HAL_OK)
  {
	Error_Handler();
  }
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;
  sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;
  sSlaveConfig.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
  sSlaveConfig.TriggerPrescaler = TIM_ICPSC_DIV4;
  sSlaveConfig.TriggerFilter = 0;
  if (HAL_TIM_SlaveConfigSynchro(&htim1, &sSlaveConfig) != HAL_OK)
  {
	Error_Handler();
  }
  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  sConfigIC.ICPrescaler = TIM_ICPSC_DIV4;
  sConfigIC.ICFilter = 0;
  if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
  {
	Error_Handler();
  }
  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
  sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI;
  if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)
  {
	Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
	Error_Handler();
  }

}

void TIM1_CC_IRQHandler(void)
{
  HAL_TIM_IRQHandler(&htim1);
}
 
7 REPLIES 7
TDK
Guru

You say it works with 1, but not 4, but the code shows it at 15.

No code actually reads the value. How do you determine it "doesn't work"?

 

I assure you the timer works with a prescaler of 1, and 4, and 15. So the bug has to be somewhere else--in your code somewhere.

If you feel a post has answered your question, please click "Accept as Solution".
Bigdan
Associate III

I'm not about 

htim1.Init.Prescaler = 15;

Yes it's works OK.

I'm about 

  sSlaveConfig.TriggerPrescaler = TIM_ICPSC_DIV4;
  sConfigIC.ICPrescaler = TIM_ICPSC_DIV4;

I'm 

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
	if (htim->Instance == TIM1) {
		if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1){
			tim1_trig_time = HAL_GetTick();
			if(tim1_isFistCaptured == 0){
				tim1_isFistCaptured=1;
			} else {
				tim1_period = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
				tim1_isFistCaptured=0;
			}
			tim1_duty = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
			__HAL_TIM_SET_COUNTER(htim, 0);
		}
	}
}

tim1_period and tim1_duty does not change after switch from TIM_ICPSC_DIV1 to TIM_ICPSC_DIV4

 

TDK
Guru

The input prescaler shouldn't substantially affect duty cycle or period. It is used to perform the IC comparison every X cycles  (prescaler > 0) instead of every cycle (prescaler = 0, default).

If you feel a post has answered your question, please click "Accept as Solution".
Bigdan
Associate III

AS I understand and It's show in https://www.youtube.com/watch?v=P6211ic2N_s&list=PLfIJKC1ud8gjLZBzjE3kKBMDEH_lUc428&index=2&ab_channel=ControllersTech

 

TIM_ICPSC_DIV4 will trigger interrupt every fourth rising edge of input signal, not every one.

So for this time timer wii count 4 times more.

I want to reduse timer interrupts. 

I think you're right. I was mixing up filter and prescaler. I may take a closer look later.

 

Apologies for the noise.

If you feel a post has answered your question, please click "Accept as Solution".

The capture divider applies only to the capture itself, i.e. not to the TI1FP1 signal which is input to the slave-mode controller. Thus, the slave-mode controller resets the counter upon every riding edge and so the capture captures duration of the last of the 4 periods.

JW

 

Bigdan
Associate III

Do you have a chance take a look? Looking forward some info.