cancel
Showing results for 
Search instead for 
Did you mean: 

Timer Capture for frequencies < 100Hz

Rogers.Gary
Senior II
Posted on February 03, 2015 at 02:20

Hello,

I am endeavoring (as with every hair-pulling experience with the STM32F4) to measure/capture LOW frequency pulses. For this, I'm assuming I need to use a 32 bit timer: TIM2 or TIM5.

This is a bit of a dilemma since TIM2 or TIM5 do not have a capture compare. So how to measure low frequency pulses?

Thank you....

#stm32f4-timer-capture-compare
12 REPLIES 12
Posted on February 03, 2015 at 02:50

This is a bit of a dilemma since TIM2 or TIM5 do not have a capture compare.

Are you sure? Both have input capture, and should clock at 84 MHz

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
Posted on February 03, 2015 at 03:48

OK: I suppose that was a silly statement without knowing for sure. But I looked in the stm32f4xx.h file and I only seen these to define the interrupt handlers for a CC:

TIM1_CC_IRQn

TIM8_CC_IRQn

How do I create an interrupt for a timer that isn't defined...?

Thanks...

Posted on February 03, 2015 at 10:42

As interrupt vectors are limited in number, most peripherals have only one vector which is shared for all interrupt sources of that peripheral. In fact, there are also vectors shared between several peripherals.

You might want to have a look at the ''capabilities'' sheet I concocted a couple of years ago http://efton.sk/STM32/STM32F4xx%20misc.pdf (usual disclaimers apply).

JW

Posted on February 03, 2015 at 16:50

TIM2_IRQn -> TIM2_IRQHandler(), all sources

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
Posted on February 03, 2015 at 17:49

Okay, to set up I did this:

void TIM2_Configuration(void)

{

    NVIC_InitTypeDef NVIC_InitStructure;

    GPIO_InitTypeDef GPIO_InitStructure;

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    

    /* TIM6 Periph clock enable */

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);

    

    /* TIM2 channel 1 pin (PA.15) configuration */

    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_15;

    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(GPIOA, &GPIO_InitStructure);

    /* Connect TIM pins to AF2 */

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource15, GPIO_AF_TIM2);

    

    /* Time base configuration */

    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

    TIM_TimeBaseStructure.TIM_Prescaler  = ((SystemCoreClock / 2) / TIMER_BASE);

    TIM_TimeBaseStructure.TIM_Period = (uint16_t)(TIMER_BASE / 10.0);    

    

    TIM_TimeBaseStructure.TIM_ClockDivision = 0;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

      

    

    //Set up TIM2 interrrupt

    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

 

 }

void main

{

    TIM2_Configuration();

    

  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_DIV1;

  TIM_ICInitStructure.TIM_ICFilter = 0x0;

  TIM_ICInit(TIM2, &TIM_ICInitStructure);

 

  /* TIM enable counter */

  TIM_Cmd(TIM2, ENABLE);

  /* Enable the CC2 Interrupt Request */

  TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);    

}

//interrupt handler

void TIM2_IRQHandler(void)

{

    if( TIM_GetITStatus(TIM2, TIM_IT_Update) )

    {

         /* Clear TIM2 Capture compare interrupt pending bit */

        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

        printf(''Living in an interrupt\n'');

    }

}

However, I cannot find 1 example of how to set up a capture/compare on channel 2. Can you direct me to an example, if there is one, as to how to set this up?

Either that, or I have a working example for Timer 1 that runs the counter /capture - bus is too fast though. I do not understand how to set the clock for that timer alone?

Thanks

Rogers.Gary
Senior II
Posted on February 03, 2015 at 17:59

I've got it working...now to figure out getting the counts and converting to frequency....

thanks...

Rogers.Gary
Senior II
Posted on February 03, 2015 at 18:17

The numbers are rolling in, but of course they are looking strange, and I believe I know what the problem may be.

At which rate should the clock be set up to run on the timer? If all of my frequencies are less than 50 Hz, should the Timer be a factor of 10 greater? 100? Any change and the numbers make less sense. Here's the interrupt code now being used (from CMSIS)

void TIM2_IRQHandler(void)

{

 

    if(TIM_GetITStatus(TIM2, TIM_IT_CC1) == SET)

    {

        /* Clear TIM1 Capture compare interrupt pending bit */

        TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);  

        

        if(uhCaptureNumber == 0)

        {

          /* Get the Input Capture value */

          uhIC3ReadValue1 = TIM_GetCapture1(TIM2);

          uhCaptureNumber = 1;

        }

        else if(uhCaptureNumber == 1)

        {

          /* Get the Input Capture value */

          uhIC3ReadValue2 = TIM_GetCapture1(TIM2);

          /* Capture computation */

          if (uhIC3ReadValue2 > uhIC3ReadValue1)

          {

            uwCapture = (uhIC3ReadValue2 - uhIC3ReadValue1);

          }

          else if (uhIC3ReadValue2 < uhIC3ReadValue1)

          {

            uwCapture = ((0xFFFF - uhIC3ReadValue1) + uhIC3ReadValue2);

          }

          else

          {

            uwCapture = 0;

          }

          /* Frequency computation */

          uwTIM1Freq = (uint32_t) SystemCoreClock / uwCapture;

          printf(''frequency = %i\n'', uwTIM1Freq);      

          uhCaptureNumber = 0;

        }

    }

}

    

Posted on February 03, 2015 at 19:33

Wow there's some chronic muddle in there...

TIM6 vs TIM2

CC1 vs CC2

The Prescaler should be ZERO, the Period should be MAXIMAL, ie 0xFFFFFFFF

TIM2 is 32-bit, use it's full range.

The math with the 0xFFFF is broken for 16-bit, and irrelevant for 32-bit.

Take TWO measurements, and delta them, ie delta = B - A

The delta is the number of ticks at the TIMCLK frequency, say 84 MHz for an STM32F4, timer on APB1.

A 50 Hz signal will have 84,000,000 / 50 ticks, so 1,680,000 ticks.

Conversely 84,000,000 / 1,680,000 = 50 (Hz)

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
Posted on February 03, 2015 at 22:10

all worked OK, thank you for the helpful post. makes sense now. I used the original function handler code from CMSIS and made vars 32 bit.

Regarding your suggestion, about delta measurements, you said to take 2 of them and subtract (2nd - 1st)  But separated by what interval of time?