cancel
Showing results for 
Search instead for 
Did you mean: 

frequency capture

madhu13
Associate II
Posted on January 10, 2011 at 13:03

frequency capture

14 REPLIES 14
lowpowermcu
Associate II
Posted on May 17, 2011 at 14:20

Hi  ulasandra,

Does the interrupt occur or not ?

MCU Lüfter

Posted on May 17, 2011 at 14:20

Seems to be reasonably viable for measuring periods shorter than 910 us (micro seconds), I don't like how it's coded, but to each their own.

You could expand the range by using a prescaler on the 72 MHz, at the expense of granularity.

And yes a cleaned up version will generate an interrupt.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
madhu13
Associate II
Posted on May 17, 2011 at 14:20

yes the interrupt occurs..

madhu13
Associate II
Posted on May 17, 2011 at 14:20

This is the fist time i just wanted to configure timer to capture the frequency, i know i can measure 1.1KHz min without using any presclar i just tried to configure the timer and measure the frequency, but i was unable to see the output becase of port pin problem, but now i got the result. Actually for our application we want to capture frequency within the range of 1Hz to 1KHz so i wanted to cascade 2 timers and and capture freq, for accuracy reason i dont want to use prescalar, i tried one way to capture and my code is as below 

//timer cascade(Timer1-master and Timer2-slave) example....

#include<stdio.h>

#include<stm32f10x_lib.h>

#include<math.h>

#define CFGR_REG_VAL  0x001D8402; //value to be written into RCC CFGR register

void RCC_Configuration(void);

void Timer1_Master(void);

void Timer2_Slave(void);

void USART_Configuration(void);

unsigned int IC1ReadValue1 = 0, IC1ReadValue2 = 0;

unsigned int CaptureNumber = 0;

unsigned long Capture = 0;

unsigned long TIM1Freq = 0;

//const int TIM1_Prescale=0;

const int System_CoreClock = 72000000;

//const int TIM3_Prescale=0;

unsigned long x;

unsigned int cap_counts=0,i;

char temp[15];

main() 

{

RCC_Configuration();

USART_Configuration();

Timer1_Master();

Timer2_Slave();

TIM1->CR1=0X1;

TIM2->CR1=0X1;

while(1)

{

 if(x>=4)

 {

   x=0;

 /* Frequency computation */  

 Capture=IC1ReadValue1+100+(IC1ReadValue2*65535);

     TIM1Freq = (System_CoreClock*100.0 / Capture);  

 cap_counts=TIM1Freq; 

 }

// cap_counts=Capture;

/* cap_counts=IC1ReadValue1;

temp[0]=(cap_counts/10000)+0X30;

cap_counts=cap_counts%10000;

temp[1]=(cap_counts/1000)+0X30;

cap_counts=cap_counts%1000;

temp[2]=(cap_counts/100)+0X30;

cap_counts=cap_counts%100;

  temp[3]=(cap_counts/10)+0X30;

cap_counts=cap_counts%10;

temp[4]=cap_counts+0X30;

temp[5]=' ';

   cap_counts=IC1ReadValue2;

temp[6]=(cap_counts/10000)+0X30;

cap_counts=cap_counts%10000;

temp[7]=(cap_counts/1000)+0X30;

cap_counts=cap_counts%1000;

temp[8]=(cap_counts/100)+0X30;

cap_counts=cap_counts%100;

  temp[9]=(cap_counts/10)+0X30;

cap_counts=cap_counts%10;

temp[10]=cap_counts+0X30; */

temp[0]=(cap_counts/10000000)+0X30;

cap_counts=cap_counts%10000000;

temp[1]=(cap_counts/1000000)+0X30;

cap_counts=cap_counts%1000000;

temp[2]=(cap_counts/100000)+0X30;

cap_counts=cap_counts%100000;

temp[3]=(cap_counts/10000)+0X30;

cap_counts=cap_counts%10000;

temp[4]=(cap_counts/1000)+0X30;

cap_counts=cap_counts%1000;

temp[5]=(cap_counts/100)+0X30;

cap_counts=cap_counts%100;

  temp[6]=(cap_counts/10)+0X30;

cap_counts=cap_counts%10;

temp[7]=cap_counts+0X30;   

//for(i=0;i<11;i++)

for(i=0;i<8;i++)

{

while((USART1->SR & 0x40)==0);

x= USART1->SR;

USART1->DR=temp[i];

}

while((USART1->SR & 0x40)==0);

x= USART1->SR;

USART1->DR=0X0A;

while((USART1->SR & 0x40)==0);

x= USART1->SR;

USART1->DR=0X0D;

}

}

void RCC_Configuration(void)

{

RCC->CSR|=0x01000000;

RCC->CR=0x00010080; //external highe speed clock enabled

if ((RCC->CR & RCC_HSE_ON)) 

{                 // if HSE enabled

while ((RCC->CR & RCC_FLAG_HSERDY)==0 ); // Wait for HSERDY = 1 (HSE is ready)

  //Flash access control reg

FLASH->ACR=0X12; //prefetch buffer enabled and flash latacy(2 wait state)

RCC->CFGR= CFGR_REG_VAL

 

  RCC->CR|=0x01000000;   //PLL enable

  if (RCC->CR & RCC_PLL_ON) 

  {                 // if PLL enabled

    while ((RCC->CR & RCC_FLAG_PLLRDY) == 0); // Wait for PLLRDY = 1 (PLL is ready)

  }  

  while ((RCC->CFGR & 0x0000008) ==0);

}      

}

void Timer1_Master(void)   

{

/* TIM1 configured in Input Capture mode and master to the Timer2 ---------------------

The external signal is connected to TIM1 CH4 pin (PA.11-pin no. 44)  

The Rising edge is used as active edge,

timer1 outputs a periodic trigger signal on each update event(UEV)

and a rising edge is output on TRGO1 on each update event, this TRGO1 

is input to the Timer2, Timer2 is configured in slave mode using ITR1,

Timer2 is put in extrenal clock mode1 which causes timer2 clocked by 

rising edge of the periodic timer1 trigger signal.

The TIM1 CCR4 and TIM2 CNT are used to compute the frequency value 

------------------------------------------------------------ */

RCC->APB2ENR|=0x800;

NVIC->ISER[0]=0X08000000;

TIM1->PSC=0x0000;

TIM1->ARR=0xffff; //Autoreload value

TIM1->CNT=0x0000;  

/////////////////////////

TIM1->CCMR2=0X3100;

TIM1->CCER=0X1000;  

//TIM1->PSC=TIM1_Prescale;

///////////////////////////

TIM1->CR1=0X0000; //URS bit is eanbled

//TIM1->EGR=0X1;

TIM1->CR2=0x20; //update event is selected as trigger o/p TRGO, here timer(master) i is used as prescalar for timer2(slave)

TIM1->DIER=0X10;

}

void Timer2_Slave(void)

{

   RCC->APB1ENR|=0x1;

TIM2->PSC=0x0000;

TIM2->ARR=0xffff; //Autoreload value

TIM2->CNT=0x0000;  

TIM2->SMCR=0x07;

}

/*USART Configuration Function*/

void USART_Configuration(void)

{

RCC->APB2ENR|=0x00004004; //USART1 clock enable

GPIOA->CRH |= (GPIOA->CRH & 0xFFFFF00F)|0x4B0;

USART1->BRR=0x271; //0x271-115200 //0x1D4C;9600 baud rate

USART1->CR1=0x00000009; //TCIE(transmit complete interrupt enable)

USART1->CR2=0x000;   //eable clock  

USART1->CR1|=0x00002000; //USART ENABLE  

}

void TIM1_CC_IRQHandler(void)

{

  if((TIM1->SR & 0X10)!=0)

  {

   /* Clear TIM1 Capture compare interrupt pending bit */

TIM1->SR&=0xefef;

   /* Get the Input Capture value */

 // IC1ReadValue1=(TIM1->CCR4+(TIM2->CNT*65535));

IC1ReadValue1 =TIM1->CCR4;

   /* Get the Input Capture value */

IC1ReadValue2=TIM2->CNT;

TIM1->CNT=0;

TIM2->CNT=0;

x++;

  }

}

but i want to configure both the timers to capture the frequency and get 32 bit count.. is it possible???(i mean after capturing  ''addition of counts in (TIM1->CCR4+TIM2->CNT) should give me the captured count value).

lowpowermcu
Associate II
Posted on May 17, 2011 at 14:20

Hi ulasandra,

You should coonsider the min and max frequency of you signal:

the min is 72 MHz /65536 ~ 1100Hz (with no prescaler on counter)

the max depends on the processing time of your IRQ 72MHz / processing time of the  IRQ. Let say it is about 100 cycles -> the max is 72MHz / 100 = 720 KHz.

Tell us what is the frequency of your signal.

MCU Lüfter

From: ulasandra.madhuri

Posted: Thursday, January 13, 2011 6:05 AM

Subject: frequency capture

yes the interrupt occurs..

Posted on May 17, 2011 at 14:20

Use the core cycle counter for a long term time base, and the TIM register for the fine grain period computations.

For example

// Cortex M3 cycle counters in the STM32's trace unit

// From http://forums.arm.com/index.php?showtopic=13949

volatile unsigned int *DWT_CYCCNT   = (volatile unsigned int *)0xE0001004; //address of the register

volatile unsigned int *DWT_CONTROL  = (volatile unsigned int *)0xE0001000; //address of the register

volatile unsigned int *SCB_DEMCR    = (volatile unsigned int *)0xE000EDFC; //address of the register

void TIM3_IRQHandler(void)

{

    static unsigned short IC3Capture1;    // 16-bit

    unsigned short IC3Capture2;

   

  static unsigned long CoreTick1;     // 32-bit

  unsigned long CoreTick2;

    unsigned long CaptureDelta, CoreTickDelta;

  unsigned long TIM3Freq = 0;

    static unsigned int CaptureNumber = 0; // State

    int i;

  if ((TIM3->SR & 0x4)!=0)

  {

    /* Clear TIM3 Capture compare interrupt pending bit */

    TIM3->SR &= 0xfbfb;

    if (CaptureNumber == 0)    // Initial capture

    {

      /* Get the Input Capture value */

      IC3Capture1 = TIM3->CCR2;

            *SCB_DEMCR = *SCB_DEMCR | 0x01000000;

            *DWT_CYCCNT = 0; // reset the counter

            *DWT_CONTROL = *DWT_CONTROL | 1 ; // enable the counter

      CoreTick1 = *DWT_CYCCNT;

      CaptureNumber = 1;

    }

    else if (CaptureNumber == 1) // Subsequent capture(s)

    {

            /* Get 32-bit base line, wraps at about a minute at 72 MHz */

      CoreTick2 = *DWT_CYCCNT;

      /* Get the Input Capture value */

      IC3Capture2 = TIM3->CCR2;

            /* Calculate Delta between two capture events, latched and then interrupts */

      CaptureDelta = (IC3Capture2 - IC3Capture1) & 0x0000FFFF;

            IC3Capture1 = IC3Capture2;

            /* Calculate Delta for core clocks, free running */

      CoreTickDelta = CoreTick2 - CoreTick1;

      CoreTick1 = CoreTick2;

            // Account for some slop in the interrupt latency

          i = (int)(CaptureDelta - (CoreTickDelta & 0x0000FFFF));

            // Get the high order word to correct magnitude, masked later

          if (i > 65000)

            CoreTickDelta -= 0x10000;

          else if (i < -65000)

            CoreTickDelta += 0x10000;

            // Low order word pulled from timer as highest precision measurement

      CoreTickDelta = (CoreTickDelta & 0xFFFF0000) | CaptureDelta;

      /* Frequency computation */

      TIM3Freq = System_CoreClock / CoreTickDelta;

      cap_freq = TIM3Freq;

    }

  }

}

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
madhu13
Associate II
Posted on May 17, 2011 at 14:20

i tried to run this example useing core cycle counter given by you now...it is capturing only1Hz to 9 Hz i am not getting accurate result above 10Hz...

Posted on May 17, 2011 at 14:20

Well that's odd. Working here on a 24 MHz VL series part at frequencies upward of 24 KHz. Should be viable to at least 60-70 KHz on a 72 MHz part, and probably higher depending on the kind of CPU utilization you can live with.

You should also consider using float math in you foreground loop, so you don't loose all the fractional results, and that measuring single periods is apt to result in some amount of jitter and modulation.
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on May 17, 2011 at 14:20

Ok, here measuring an external frequency source (ie not synchronous with the CPU clock)

24000.0000 23976.0240 24000.0000 24000.0000 24000.0000 23976.0240 24000.0000

 

24000.0000 24000.0000 24000.0000 24000.0000 24000.0000 23976.0240 24000.0000

 

23976.0240 24000.0000 24000.0000 24000.0000 23976.0240 24000.0000 24000.0000

 

24000.0000 24000.0000 24000.0000 24000.0000 24000.0000 24000.0000 24000.0000

 

24000.0000 24000.0000 24000.0000 24000.0000 23976.0240 24000.0000 24000.0000

 

24000.0000 24000.0000 24000.0000 24024.0240 24000.0000 24000.0000 24000.0000

 

24000.0000 24000.0000 24000.0000 24000.0000 24000.0000 24000.0000 24000.0000

 

24000.0000 24000.0000 24000.0000 24000.0000 24000.0000 24000.0000 24000.0000

 

24000.0000 24000.0000 24024.0240 24000.0000 24000.0000 24000.0000 24000.0000

 

24000.0000 24000.0000 24000.0000 24000.0000 24000.0000 24000.0000 23976.0240

 

24000.0000 23976.0240 24000.0000 24000.0000 24000.0000 23976.0240 24000.0000

 

24000.0000 23976.0240 24000.0000 24000.0000 24024.0240 24000.0000 24000.0000

 

23976.0240 24000.0000 24000.0000 23976.0240 23976.0240 24000.0000 24000.0000

 

24000.0000 24000.0000 24000.0000 23976.0240 24000.0000 24000.0000 24000.0000

 

24000.0000 24000.0000 23976.0240 23976.0240 24000.0000 24000.0000 24024.0240

 

24000.0000 24000.0000 24000.0000 24000.0000 24000.0000 24000.0000 23976.0240

 

23976.0240 23976.0240 24000.0000 24000.0000 24000.0000 23976.0240 24000.0000

 

24000.0000 24000.0000 24000.0000 24000.0000 24024.0240 24000.0000 24000.0000

 

    9.9991     9.9991     9.9991     9.9991     9.9991     9.9991     9.9991

 

    9.9991     9.9991     9.9991     9.9991     9.9991     9.9991     9.9991

 

    9.9991     9.9991     9.9991     9.9991     9.9991     9.9991     9.9991

 

    9.9991     9.9991     9.9991     9.9991     9.9991     9.9991     9.9991

 

    9.9991     9.9991     9.9991     9.9991     9.9991     9.9991     9.9991

 

    9.9991     9.9991     9.9991     9.9991     9.9991     9.9991     9.9991

 

    9.9991     9.9991     9.9991     9.9991     9.9991     9.9991     9.9991

 

    9.9991     9.9991     9.9991     9.9991     9.9991     9.9991    10.0003

 

   10.0003    10.0003    10.0003    10.0003    10.0003    10.0003    10.0003

 

   10.0003    10.0003    10.0003    10.0003    10.0003    10.0003    10.0003

 

   10.0003    10.0003    10.0003    10.0003    10.0003    10.0003    10.0003

 

   10.0003    10.0003    10.0003    10.0003    10.0003    10.0003    10.0003

 

   10.0003    10.0003    10.0003    10.0003    10.0003    10.0003    10.0003

 

   10.0003    10.0003    10.0003    10.0003    10.0003    10.0003    10.0003

 

   10.0003    10.0003    10.0003    10.0003    10.0003    10.0003    10.0003

 

   10.0003    10.0003    10.0003    10.0003    10.0003    10.0003    10.0003

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