cancel
Showing results for 
Search instead for 
Did you mean: 

TIMx Input Capture Prescaler does not work

David Brooks
Associate II
Posted on October 21, 2015 at 13:26

I'm experiencing a problem very similar to the post titled ''Design Anomaly with TIMx...'' using the STM32F429i-DISCO Board and IAR Workbench. Despite several related posts, I have not found a solution. My 2-channel frequency measuring code is working fine. I enable input capture via HAL_TIM_IC_Start(), wait for 1ms and then call HAL_TIM_IC_Stop(). I read the data at the end of the 1ms just fine, and as I am expecting, it appears all registers get reset upon capture and I wind up with a new capture on every rising edge of the signal on TI2 during that 1ms period. However, when I change the prescaler from 1 to 8 in order to make better use of the 16/32 bit range, the captured count is the same as when the prescaler was 1. It seems the prescaler is not working or is not ''enabled''.  My code originated with the Cube PWM Example. Although I have modified that code to meet my needs, I checked my manually-written code against Cube-generated code and the two appear consistent.

5 REPLIES 5
Posted on October 21, 2015 at 13:54

> However, when I change the prescaler from 1 to 8

How?

Are you talking about the capture prescale (TIMx_CCMRy.ICzPSC) or the timer-clock prescale (TIMx_PSC)?

Check/post the content of TIMx_CCMRy and TIMx_CCER after the change.

JW

Posted on October 21, 2015 at 14:31

Used Input Prescaler on F2 and F4 parts to measure the LSE/LSI via TIM5 (as I recall), where DIV8 worked as designed.

Might want to consider the input frequency, the input synchronizer and the Clock Division setting as these would tend to limit the maximum observable speed.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
David Brooks
Associate II
Posted on October 21, 2015 at 15:29

I am talking about TIMx_CCMRy.ICzPSC. I am not changing the prescaler on the fly. It is configured at startup by MX_TIMx_Init(). BTW, I am using TIM1 and TIM4.

I set a breakpoint after the 1ms period and before I execute HAL_TIM_IC_Stop and CMR1_Input = 0x00000D00 and CCER=0x00000010, which I think are both correct.

static void MX_TIM_Init(TIM_HandleTypeDef *htim, TIM_TypeDef *Timer)

{

  TIM_ClockConfigTypeDef sClockSourceConfig;

  TIM_SlaveConfigTypeDef sSlaveConfig;

  TIM_MasterConfigTypeDef sMasterConfig;

  TIM_IC_InitTypeDef sConfigIC;

  htim->Instance = Timer;

  htim->Init.Prescaler = 0;

  htim->Init.CounterMode = TIM_COUNTERMODE_UP;

  htim->Init.Period = 0xffff;

  htim->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

  /* This call is not used in this App and corrupts TIM4 */

  /* htim->Init.RepetitionCounter = 0; */

  if (HAL_TIM_Base_Init(htim) != HAL_OK)

  {

    /* Initialization Error */

    Error_Handler(TIM_Error);

  }

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

  HAL_TIM_ConfigClockSource(htim, &sClockSourceConfig);

  HAL_TIM_IC_Init(htim);

  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;

  sSlaveConfig.InputTrigger = TIM_TS_TI2FP2;

  sSlaveConfig.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING;

  sSlaveConfig.TriggerFilter = 0;

  HAL_TIM_SlaveConfigSynchronization(htim, &sSlaveConfig);

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

  HAL_TIMEx_MasterConfigSynchronization(htim, &sMasterConfig);

  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;

  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;

  sConfigIC.ICPrescaler = TIM_ICPSC_DIV8;

  sConfigIC.ICFilter = 0;

  HAL_TIM_IC_ConfigChannel(htim, &sConfigIC, TIM_CHANNEL_2);

}

David Brooks
Associate II
Posted on October 21, 2015 at 15:34

Note that my maximum input frequency is 1.8 MHz, which results in a captured count of only 98 and an error of about 2%. Hence the reason I want to use the prescaler.

Posted on October 21, 2015 at 16:24

Ah, so it's not that there is no capture - it's that the captured value is unexpected.

> sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;

>  sSlaveConfig.InputTrigger = TIM_TS_TI2FP2;

This won't work.

Look at the input capture circuit schematics in RM (RM0090 rev.10 Fig.159). The capture trigger (IC1PS) is after the divider, whereas you reset the counter from TI2FP2 which is before the divider (on that figure, TI1FP1, as it's for channel 1).

Thus, you will reset the counter 8x before one capture; and the last reset occurs exactly one edge before the capture.

The workaround is trivial: don't reset. Subtract values from two successive captures rather.

JW

[EDIT] Post edited, as I overlooked '' the captured count is the same as when the prescaler was 1'' and thought you see 0 as the captured value, sorry