2016-07-27 12:37 AM
Hi. I'm having problem trying to use input capture mode to measure frequency. I create pwn signal from timer4 of microprocessor and try to mesure it's frequency via timer2 input capture. I also measure the frequncy via ossiloscope. The problem is frequencies I measure from ossiloscope an input capture don't match. I have deviation. For higher frequencies higher deviation. For example for 5000Hz I measure 5084, for 87kHz I measure 131kHz.
My code is below. Pelease help me.#include <stm32f4xx.h>uint32_t count;float frequency;int main(){ GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_ICInitTypeDef TIM_ICInitStructure; NVIC_InitTypeDef NVIC_InitStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_HSEConfig(RCC_HSE_ON); while(!RCC_GetFlagStatus(RCC_FLAG_HSERDY)); RCC_SYSCLKConfig(RCC_SYSCLKSource_HSE); RCC_PCLK2Config(RCC_HCLK_Div1); RCC_PCLK1Config(RCC_HCLK_Div1); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); //Kesme NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_Init(&NVIC_InitStructure); //GPIOD pwm output GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOD,&GPIO_InitStructure); GPIO_PinAFConfig(GPIOD,GPIO_PinSource15,GPIO_AF_TIM4); //GPIOA bit 0 capture input GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM2); //TIMER4 pwm adjustments TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_Period = 800/9; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Prescaler = 0; TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_Pulse = 40-1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC4Init(TIM4,&TIM_OCInitStructure); //TIM2 capture adjustments TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; 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 = 0; TIM_ICInit(TIM2,&TIM_ICInitStructure); TIM_ClearFlag(TIM2,TIM_FLAG_CC1); TIM_ITConfig(TIM2,TIM_IT_CC1,ENABLE); TIM_SetCounter(TIM2,0); TIM_Cmd(TIM4,ENABLE); TIM_Cmd(TIM2,ENABLE); while(1) { } }void TIM2_IRQHandler(){ count = TIM_GetCapture1(TIM2); frequency = 64000000.0/count; TIM_SetCounter(TIM2,0); TIM_ClearFlag(TIM2,TIM_FLAG_CC1); }2016-07-27 01:51 AM
I'd qualify the interrupt source and clear it earlier.
Consider PWM Input mode2016-08-04 03:31 AM
2016-08-04 03:59 AM
Floating-point constants are double by default, thus the division is performed in double, for which there is no hardware.
Use the f suffix for the constant. JW