cancel
Showing results for 
Search instead for 
Did you mean: 

Input capture

Fabio Romeo
Associate II
Posted on July 07, 2017 at 17:44

Input capture Interrupt ignored.

Hi all. I have an STM32F429II. I am trying simply to use the input capture functionality for an external signal that pulses with 200 ms period.

The issue is that can't see the interrupt raising.

That's my code to init the IC :

void TIM_Config(void)

{

/* GPIOH clock enable */

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH, ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_Init(GPIOH, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOH, GPIO_PinSource11, GPIO_AF_TIM5); // Connect TIM pins to AF2

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn ;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;// era 0

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // era 1

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;// Enable the TIM5 global Interrupt

NVIC_Init(&NVIC_InitStructure);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);

TIM_ICInitTypeDef TIM_InputCaptureInitStructure;

TIM_InputCaptureInitStructure.TIM_Channel = TIM_Channel_1;

TIM_InputCaptureInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;

TIM_InputCaptureInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;

TIM_InputCaptureInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

TIM_InputCaptureInitStructure.TIM_ICFilter = 0x0;

TIM_ICInit(TIM5, &TIM_InputCaptureInitStructure);

/* Enable the CC1 Interrupt Request */

TIM_ITConfig(TIM5, TIM_IT_CC1, ENABLE);

/* TIM enable counter */

TIM_Cmd(TIM5, ENABLE);

}

And this is the Interrupt routine :

void TIM5_IRQHandler(void)

{ if (TIM_GetITStatus(TIM5, TIM_IT_CC1) == SET)

{

TIM_ClearITPendingBit(TIM5, TIM_IT_CC1);

rpm4 = TIM_GetCapture1(TIM5);

static char xx[12];

sprintf( xx, ' %l', rpm4 );

GUI_DispStringAt(xx,100,150);

}

TIM_ClearITPendingBit(TIM5, TIM_IT_CC1);

}

I put some breakpoints inside the Interrupt routine but nothing happens...

My external signal is a 5V signal ( this micro is 5V tolerant... ) with negative pulses...

-------- -------- ---------

|_| |_|

Any clue ?

Thanks in advance

Fabio

Note: this post was migrated and contained many threaded conversations, some content may be missing.
10 REPLIES 10
S.Ma
Principal
Posted on July 07, 2017 at 21:25

If I remember well, you miss one function to enable the capture/compare of the timer.

If using debug mode, put a breakpoint after running the code, look at the timer registers values (especially the capture control register bits), and then once you find out what's missing, look for how to flip the missed bit within library to dig up the right function. Alternate way would be to check a working reference example.

Posted on July 07, 2017 at 21:29

PH11 is Channel 2 (TIM5_CH2)

For CC1 to fire you'd need to use indirect mode.

If using C++ or .cpp file you'd also need to use extern 'C' for the IRQ Handler

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on July 10, 2017 at 11:44

Thanks Clive One, good point for extern 'C',  I forgot it was a Cpp file. I changed the CC to 2 but nothing changed. Are we sure that this feature works for 5V -- 0V signals ?

Posted on July 10, 2017 at 13:46

Hi, I tried to do what you suggest. The CCR2 register ( in the meantime I moved from channel1 to channel2 ) seems moving randomly to casual values...

Posted on July 10, 2017 at 16:41

Pretty sure a 5V pulse would be fine. If you are concerned that is the cause, use another TIM to generate the pulse train test signal at 3V CMOS levels, and check that.

I'd properly initialize the TIM, rather than assume just setting up the IC and ignoring the timebase will work. I'm trying to avoid having to rewrite every piece of broken code that gets posted, especially when such code isn't free standing.

Here is an example of TIM2, a 32-bit timer, using PWM Input mode, where the counter resets rather than you having to compute a delta measurement

/**************************************************************************************/
//
// Portion from
// STM32 RC Servo Demo for 168 MHz STM32F4 Discovery - sourcer32@gmail.com
//
/**************************************************************************************/
volatile uint32_t Reading[2]; // Readings from PA0 TIM2_CH1 (1us units)
void TIM2_IRQHandler(void)
{
 if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
 {
 TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
 Reading[0] = TIM_GetCapture1(TIM2); // Period (us) ~20000
 Reading[1] = TIM_GetCapture2(TIM2); // Duty/Width (us) ~1500 or whatever (600-2400 us)
 }
}
/**************************************************************************************/
void TIM2_Configuration(void)
{
 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
 TIM_ICInitTypeDef TIM_ICInitStructure;
 GPIO_InitTypeDef GPIO_InitStructure;
 NVIC_InitTypeDef NVIC_InitStructure;
 /* TIM2 clock enable */
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
 /* GPIO clock enable */
 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
 /* Configure GPIO input for timer */
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // PA0 TIM2_CH1_ETR (using CH1)
 GPIO_Init(GPIOA, &GPIO_InitStructure);
 /* Connect TIM2 pins to AF */
 GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_TIM2);
 /* Enable the TIM2 global Interrupt */
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
 NVIC_Init(&NVIC_InitStructure);
 /* Time base configuration - SystemCoreClock = 168000000 for 168 MHz board ABP1 @ 42 MHz (DIV4) */
 TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) (((SystemCoreClock / 1000000) / 2) - 1); // Shooting for 1 MHz, (1us)
 TIM_TimeBaseStructure.TIM_Period = 0xFFFFFFFF; // Maximal (32-bit)
 TIM_TimeBaseStructure.TIM_ClockDivision = 0;
 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
 /* Configure PWM Input Capture */
 TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; // PA0 TIM2_CH1
 TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
 TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
 TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
 TIM_ICInitStructure.TIM_ICFilter = 0x0;
 TIM_PWMIConfig(TIM2, &TIM_ICInitStructure);
 /* Select the TIM2 Input Trigger: TI1FP1 */
 TIM_SelectInputTrigger(TIM2, TIM_TS_TI1FP1);
 /* Select the slave Mode: Reset Mode */
 TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);
 TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);
 /* TIM Interrupts enable */
 TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);
 /* TIM2 enable counter */
 TIM_Cmd(TIM2, ENABLE);
}
/**************************************************************************************/
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on July 13, 2017 at 17:21

Hi Clive. I tried to use your code changing just the IO port to mine, H11.

volatile uint32_t Reading[2]; // Readings from PA0 TIM2_CH1 (1us units)

void TIM2_IRQHandler(void)

{

  if(TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)

  {

   TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);

   Reading[0] = TIM_GetCapture1(TIM2); // Period (us) ~20000

   Reading[1] = TIM_GetCapture2(TIM2); // Duty/Width (us) ~1500 or whatever (600-2400 us)

  }

}

/**************************************************************************************/

void TIM2_Configuration(void)

{

 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

 TIM_ICInitTypeDef TIM_ICInitStructure;

 GPIO_InitTypeDef GPIO_InitStructure;

 NVIC_InitTypeDef NVIC_InitStructure;

/* TIM2 clock enable */

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

 /* GPIO clock enable */

 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH, ENABLE);

 /* Configure GPIO input for timer */

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //era PA0 TIM2_CH1_ETR (using CH1)

 GPIO_Init(GPIOH, &GPIO_InitStructure);

/* Connect TIM2 pins to AF */

 GPIO_PinAFConfig(GPIOH, GPIO_PinSource11, GPIO_AF_TIM2);

/* Enable the TIM2 global Interrupt */

 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;

 NVIC_Init(&NVIC_InitStructure);

 /* Time base configuration - SystemCoreClock = 168000000 for 168 MHz board ABP1 @ 42 MHz (DIV4) */

 TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) (((SystemCoreClock / 1000000) / 2) - 1); // Shooting for 1 MHz, (1us)

 TIM_TimeBaseStructure.TIM_Period = 0xFFFFFFFF; // Maximal (32-bit)

 TIM_TimeBaseStructure.TIM_ClockDivision = 0;

 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Down;

 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

 /* Configure PWM Input Capture */

 TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; // PA0 TIM2_CH1

 TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;

 TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; // FRC TIM_ICSelection_DirectTI;

 TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

 TIM_ICInitStructure.TIM_ICFilter = 0x0;

 TIM_PWMIConfig(TIM2, &TIM_ICInitStructure);

 /* Select the TIM2 Input Trigger: TI1FP1 */

 TIM_SelectInputTrigger(TIM2, TIM_TS_ETRF);// FRC

 /* Select the slave Mode: Reset Mode */

 TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);

 TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);

 /* TIM Interrupts enable */

 TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);

 /* TIM2 enable counter */

 TIM_Cmd(TIM2, ENABLE);

}

my breakpoint, put inside the irq handler, never starts.

I observed the related CNT register changing its value when no impulse is given to the PH11. Is it normal ?

Fabio

Posted on July 13, 2017 at 17:23

Clive. You reported that PH11 is channel 2 : where is available that information ? I tried also with channel 2 in the previous code with same results.

Fabio

Posted on July 13, 2017 at 18:01

That would be in the Data Sheet for your part

http://www.st.com/content/ccc/resource/technical/document/datasheet/03/b4/b2/36/4c/72/49/29/DM00071990.pdf/files/DM00071990.pdf/jcr:content/translations/en.DM00071990.pdf

 

TIM2 is not associated with PH11, which is TIM5_CH2

CNT register is a free running counter at the configured timebase clock speed. You want this to latch into CCR2, or one of the other capture registers to time stamp the event.

So you'd need to modify the code to use the 16-bit TIM5, or experiment with the example as presented, using the pins I used.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on July 13, 2017 at 20:15

Unfortunately I can only use that PH11 ... the only one free and accessible pin I have. 

I had that document, now I found that using TIM5_CH2 keyword...

May you explain me the reason for use : 

   TIM_SelectInputTrigger(TIM2, TIM_TS_ETRF);// FRC 

and the second parameter type ? In all of the examples  I saw it was not used.

As well as the following.

TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);

TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);

thanks in advance.

Fabio