2011-01-10 04:03 AM
frequency capture
2011-05-17 05:20 AM
Hi ulasandra,
Does the interrupt occur or not ?MCU Lüfter2011-05-17 05:20 AM
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.2011-05-17 05:20 AM
yes the interrupt occurs..
2011-05-17 05:20 AM
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).2011-05-17 05:20 AM
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üfterFrom: ulasandra.madhuriPosted: Thursday, January 13, 2011 6:05 AMSubject: frequency captureyes the interrupt occurs..
2011-05-17 05:20 AM
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; } } }2011-05-17 05:20 AM
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...
2011-05-17 05:20 AM
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.2011-05-17 05:20 AM
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