cancel
Showing results for 
Search instead for 
Did you mean: 

input capture pwm input mode precision

andrewcarp
Associate II
Posted on March 17, 2014 at 17:39

Hello,

I am writing code to capture an incoming square wave frequency. Here is my initialization code:

TIM_ICInitTypeDef TIM_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
// GPIOB clock enable 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
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_UP ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Connect TIM pin to AF2 
GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_TIM5);
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV8;
TIM_ICInitStructure.TIM_ICFilter = 0x2;
TIM_PWMIConfig(TIM5, &TIM_ICInitStructure);
TIM_SelectInputTrigger(TIM5, TIM_TS_TI2FP2);
/* Select the slave Mode: Reset Mode */
TIM_SelectSlaveMode(TIM5, TIM_SlaveMode_Reset);
TIM_SelectMasterSlaveMode(TIM5,TIM_MasterSlaveMode_Enable);
/* TIM enable counter */
TIM_Cmd(TIM5, ENABLE);
TIM_ITConfig(TIM5, TIM_IT_CC2, ENABLE);

And here is my interrupt code:

RCC_ClocksTypeDef RCC_Clocks;
RCC_GetClocksFreq(&RCC_Clocks);
TIM_ClearITPendingBit(TIM5, TIM_IT_CC2); //perhaps changing this to cc1
/* Get the Input Capture value */
IC2Value = TIM_GetCapture2(TIM5);
if (IC2Value != 0)
{
/* Duty cycle computation */
DutyCycle = (TIM_GetCapture1(TIM5) * 100) / IC2Value;
Frequency = (RCC_Clocks.HCLK_Frequency)/2 / IC2Value;
}
else
{
DutyCycle = 0;
Frequency = 0;
}

At frequencies of about 1.02 MHz, I am getting inaccurate readings, like 1.223051MHz. Is there a way to tune this in more? or do I have to characterize it like a noisy sensor? Thanks for your help. #stm32f4 #discovery #timers
2 REPLIES 2
Posted on March 17, 2014 at 18:11

Interrupting at 1 MHz is a bit high, wouldn't been reading/computing the processor speed at each interrupt.

Do you appreciate what the DIV8 is doing?

The precision would depend on the frequency and stability of clock being provided to the timer. The speed would determine the measurement granularity. The input to the timer is resynchronized to the internal clock.

The other method to compute frequency would be as an external counter, measured over a defined period.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
andrewcarp
Associate II
Posted on March 17, 2014 at 22:44

Yes, I believe that I 'appreciate' the DIV8 parameter.  If I understand it correctly, it only throws an interrupt once every 8 events, and that is what I am using so that the rest of my code can run, otherwise it would simply interrupt constantly.  I might have missed this in the datasheet, but I assumed that the timer could input capture at 1/168th the clock speed.  I am actually intending it for frequencies of roughly 2MHZ and a bit above.  

Also, clive1, I liked your old user pic better.