Skip to main content
Graduate
April 17, 2025
Question

stm32g0 timer input capture division does not work

  • April 17, 2025
  • 4 replies
  • 671 views

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);
}
 
    This topic has been closed for replies.

    4 replies

    Super User
    April 17, 2025

    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.

    BigdanAuthor
    Graduate
    April 17, 2025

    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

     

    Super User
    April 17, 2025

    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).

    BigdanAuthor
    Graduate
    April 17, 2025

    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. 

    Super User
    April 17, 2025

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

     

    Apologies for the noise.

    Super User
    April 17, 2025

    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