2017-07-07 08:44 AM
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 AF2NVIC_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.2017-07-07 12:25 PM
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.
2017-07-07 12:29 PM
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
2017-07-10 04:44 AM
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 ?
2017-07-10 06:46 AM
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...
2017-07-10 09:41 AM
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);
}
/**************************************************************************************/
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2017-07-13 10:21 AM
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
2017-07-13 10:23 AM
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
2017-07-13 11:01 AM
That would be in the Data Sheet for your part
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.
2017-07-13 01:15 PM
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