2016-08-05 12:15 PM
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 changedTIM_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
2016-08-05 01:04 PM
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.2016-08-08 07:16 AM
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.
2016-08-08 07:49 AM
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