cancel
Showing results for 
Search instead for 
Did you mean: 

stm32f10x - Input capture

fntheirs
Associate
Posted on August 05, 2016 at 21:15

Hi everyone,

I'm using the stm32f10x to measure a pulse width and I followed the Input Capture example but I still have some errors. The measurement is erratic, sometimes the value is ok and most of the times it's wrong. What I need to do, is measure the time high from a pulse. I don't know if this pulse is comming periodically or not, so the period measurement doesn't work for me. As you can see I changed

TIM_ICPolarity_Rising for

TIM_ICPolarity_BothEdge. Do I need to change something else to get the pulse width?

Sorry if it's a newbie question but I started on Monday with this MCU and I'm a little bit confuse. Many thanks, Fernando

//Remmaping TIM3_CH2 PA0 --> PC7
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);
/* TIM3 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* GPIOC clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
/* TIM3 channel 2 pin (PC.07) configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
TIM_DeInit(TIM3);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_BothEdge;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM3, &TIM_ICInitStructure);
/* TIM enable counter */
TIM_Cmd(TIM3, ENABLE);
/* Enable the CC2 Interrupt Request */
TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);
TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);
/* Enable the TIM3 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/////////////////////////////////////////////////////////////////////////////////////////
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3, TIM_IT_CC2) == SET) 
{
/* Clear TIM3 Capture compare interrupt pending bit */
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
if(CaptureNumber == 0)
{
/* Get the Input Capture value */
IC3ReadValue1 = TIM_GetCapture2(TIM3);
CaptureNumber = 1;
}
else if(CaptureNumber == 1)
{
/* Get the Input Capture value */
//IC3ReadValue2 = TIM_GetCapture2(TIM3); 
/* Capture computation */
if (IC3ReadValue2 > IC3ReadValue1)
{
Capture = (IC3ReadValue2 - IC3ReadValue1); 
}
else
{
Capture = ((0xFFFF - IC3ReadValue1) + IC3ReadValue2); 
}
/* Frequency computation */ 
TIM3Freq = (uint32_t) SystemCoreClock / Capture;
CaptureNumber = 0;
}
}
}

#stm32f10x #inputcapture
3 REPLIES 3
Posted on August 05, 2016 at 22:04

For measuring pulse width, I'd probably use the PWM Input mode, which pairs Ch1 and Ch2 to provide period and duty information.

You have copied ST's math for computing delta measurements, which is broken. You can in fact subtract any uint16_t values within the number space without any consideration if one is larger than the other.

You should perhaps pay more attention to the time base configuration, as the 16-bit range and source clock is going to significantly impact the speed of signals you can accurately measure.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
fntheirs
Associate
Posted on August 08, 2016 at 16:16

Thanks for the answer Clive! I'd like to ask you a couple of question, just to check if I get this clear.

With this line, the MCU resets the counter on every rising edge, so if I trigger the interrupt on every falling edge I should get what I need.

TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);

That would be this line:

TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;

And the other thing is the prescaler (I realized that I have configured it wrong). The MCU's frequency is 72MHz, so if I want: 1 tick per 1 µS:

TIM_TimeBaseStructure.TIM_Prescaler =72;

1 tick per 10 uS:

TIM_TimeBaseStructure.TIM_Prescaler =720

And so on... I dont get it because I saw that many people set the prescaler in (72-1), I don't understand why there is a (-1) there. Isn't this number the clock divisor? So, 72Mhz / 72 = 1MHz My interrupt handler is now:

void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
{
/* Clear TIM3 Capture compare interrupt pending bit */
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
/* Get the Input Capture value */
IC2Value = TIM_GetCapture2(TIM3);
if (IC2Value != 0)
{
/* Duty cycle computation */
DutyCycle = (TIM_GetCapture1(TIM3) * 100) / IC2Value;
/* Frequency computation */
Frequency = SystemCoreClock / IC2Value;
}
else
{
DutyCycle = 0;
Frequency = 0;
}
}
}

And

IC2Value is the T_high from the input signal.

Posted on August 08, 2016 at 16:49

I dont get it because I saw that many people set the prescaler in (72-1), I don't understand why there is a (-1) there. Isn't this number the clock divisor? So, 72Mhz / 72 = 1MHz

When you have a count of N states, in counts from 0 to N-1, the silicon has a comparator for the last state (N-1) so the NEXT state transitions to ZERO.

ie 0..71, 0..71, etc each sequence having 72 states

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..