CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

measure frequency ccp1 - measuring twice the value

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
fvnktion



Joined: 27 Jun 2006
Posts: 39

View user's profile Send private message

measure frequency ccp1 - measuring twice the value
PostPosted: Thu Aug 27, 2009 3:34 pm     Reply with quote

Just trying to figure out why I am occasionally getting twice the expected value for a measured rising edges of a pulse.

Below is the code and terminal output of the measured pulse time, (not actually the period as labeled). I thought that i may be because of interrupt latency, so turned on the pll to get 4x the speed from the processor and still see the problem of double the period values expected.

Is there something beyond missing an interrupt due to latency going on here? How would i fix the problem?

Code:

//***************************************************************
////using ccp1 to measure pulse
//***************************************************************
#define HS_PLL
#include <18F4520.H>
#fuses HS, NOWDT, NOPROTECT,PUT, NOLVP
#use delay(clock = 8000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#include "D:\PIC_Code\My_Drivers\lcd_picdem2_2.c"

//globals
static int1 fHit = 0;
static int nHits = 1;
int16 timeC = 0, timeL = 0;//current time and Last time


//**********************************************************
//measure the time from rising egdes then process
//**********************************************************
#int_ccp1
void isr_ext(){

if(nHits==1){
   timeL = ccp_1;
   nHits=2;
}
else if(nHits==2){
   timeC = CCP_1;//get ccp value
   fHit=1;  //flag for processing
   disable_interrupts(GLOBAL);//disable until processed
   nHits=1;//reset nHits to start over
}
}//isr


//***********************************************************
main()
{
int8 i = 0;
int16 period = 0, freq = 0;

#ifdef HS_PLL
setup_oscillator(OSC_32MHZ|OSC_PLL_ON);
#endif

//setup timer1 to measure pulses
SETUP_TIMER_1(T1_INTERNAL|T1_DIV_BY_1);
#define DIVIDER 1
//setup ccp1 for interrupt of pulse measurement
CLEAR_INTERRUPT(INT_CCP1);
SETUP_CCP1(CCP_CAPTURE_RE);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);


lcd_init();
delay_ms(10);
printf(lcd_putc,"\fstarted...");
printf("\n\rstarted...");

while(1){

if(fHit){
   printf("\r\nPeriod:%lu",timeC-timeL);
   fHit = 0;//processed hit
   enable_interrupts(GLOBAL);   
}//if

}//while
}

//************************************************************
//debug data when inputting 500khz missing interrupt every 18th cycle
//output
/*
Period:500
Period:250
Period:250
Period:250
Period:250
Period:250
Period:250
Period:250
Period:250
Period:250
Period:250
Period:250
Period:250
Period:250
Period:250
Period:250
Period:250
Period:250
*/
/*
//input at 16khz:
Period:250
Period:125
Period:125
Period:125
Period:125
Period:125
Period:125
Period:125
Period:125
Period:125
Period:125
Period:125
Period:125
Period:125
Period:125
Period:125
Period:125
Period:125
Period:125
*/
//input at 32khz
/*
Period:63
Period:124
Period:125
Period:63
Period:62
Period:63
Period:62
Period:125
Period:125
Period:63
Period:62
Period:125
Period:125
Period:62
Period:63
Period:62
Period:125
Period:125
Period:63
Period:62
Period:63
Period:125
Period:125
Period:63
*/
//input at 32khz with the pll enabled running at 32Mhz
/*
Period:125
Period:125
Period:62
Period:63
Period:62
Period:125
Period:125
Period:62
Period:63
Period:62
Period:125
Period:125
Period:63
Period:62
Period:63
Period:125
Period:125
Period:63
*/
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Aug 27, 2009 4:10 pm     Reply with quote

I assume you have an 8 MHz external crystal (and associated capacitors).
If so, this program shows how to run it in PLL mode:
Code:
#include <18F4520.H>
#fuses H4, NOWDT, NOPROTECT,PUT, NOLVP
#use delay(clock = 32000000)

//====================================
void main()
{

// Do a short blink on an LED, once per second.
while(1)
  {
   output_high(PIN_B0); 
   delay_ms(100);
   output_low(PIN_B0);
   delay_ms(900);
  }

}


Note the H4 fuse. Note the 32 MHz in the #use delay(), and note that
setup_oscillator() is not used.
fvnktion



Joined: 27 Jun 2006
Posts: 39

View user's profile Send private message

PostPosted: Fri Aug 28, 2009 9:17 am     Reply with quote

Thanks for the info PCM.

I made the changes and the pll is now working. However i still get the same problem of a period measuring twice what it should.

I am trying to figure out what the maximum signal frequency i can detect with the ccp module. I know that that it can be dependent on the ISR overhead and have done the following measurements and calcluations to see if what should feasibly be able to pick up a 32 khz signal with a system frequency of 32Mhz. I hope you can clear me up on anything that I am missing here.

Maximum frequency of signal that can be detected:
(ISR overhead instructions + ISR instructions)

I measured the delay in getting the to ISR on a scope of a maximum of 6.5 us = 52 instructions. ISR instructions = 24 instructions. With the clock running at 32Mhz. (ISR overhead + ISR instruction) = 76 instructions = 9.5 us. Calcualting frequency that I should be able to detect < 1/9.5us = 105khz.

So running the clock at 32Mhz and having an ISR total overhead of 9.5us I should be able to detect a signal of less than 105khz without missing a rising edge.

Are these calcuations correct? What else do I need to take into account?

If this is correct or close to correct. Why am i missing a rising edge with an input signal of 32khz = 31.25us period. I should have plenty of time of being able to get the ISR to detect ALL rising edges.

Thanks for the help.
fvnktion



Joined: 27 Jun 2006
Posts: 39

View user's profile Send private message

PostPosted: Fri Aug 28, 2009 9:21 am     Reply with quote

Here is the updated code that i used to measure a 32khz signal with the processor running at 32Mhz. Attached is also the output of period showing a periodic 2X measurement.

Using compiler: 4.083

Code:
//***************************************************************
////using ccp1 to measure pulse
//***************************************************************
#include <18F4520.H>
#fuses H4 //to enable PLL
#fuses NOWDT, NOPROTECT,PUT, NOLVP
#use delay(clock = 32000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

//#include "D:\PIC_Code\My_Drivers\lcd_picdem2_2.c"
#include "D:\PIC_Code\My_Drivers\lcd_picdem2.c"

#define TEST_LED pin_b3

//globals
static int1 fHit = 0;
static int nHits = 1;
int16 timeC = 0, timeL = 0;


//****************************************************************
//measure the time from rising egdes then process
//****************************************************************
#int_ccp1
void isr_ext(){
output_low(TEST_LED);
output_high(TEST_LED);
if(nHits==1){
   timeL = ccp_1;
   nHits=2;
}
else if(nHits==2){
   timeC = CCP_1;//get ccp value
   fHit=1;  //flag for processing
   disable_interrupts(GLOBAL);//disable until processed
   nHits=1;//reset nHits to start over
}
}//isr


//***********************************************************
main()
{
int8 i = 0;
int16 period = 0, freq = 0;

//setup timer1 to measure pulses
SETUP_TIMER_1(T1_INTERNAL|T1_DIV_BY_1);
#define DIVIDER 1
//setup ccp1 for interrupt of pulse measurement
CLEAR_INTERRUPT(INT_CCP1);
SETUP_CCP1(CCP_CAPTURE_RE);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);


lcd_init();
delay_ms(10);
printf(lcd_putc,"\fstarted...");
printf("\n\rstarted...");

while(1){

if(fHit){
   printf("\r\nPeriod:%lu",timeC-timeL);
   printf(lcd_putc,"\fperiod:%lu",timeC-timeL);
   fHit = 0;//processed hit
   enable_interrupts(GLOBAL);   
}//if

   //disable_interrupts(GLOBAL);
output_low(TEST_LED);
output_high(TEST_LED);
}//while
}



//terminal output:
Period:250
Period:250
Period:500
Period:250
Period:250
Period:250
Period:250
Period:250
Period:250
Period:249
Period:250
Period:250
Period:250
Period:250
Period:250
Period:250
Period:250
Period:250
Period:250
Period:250
Period:506
Period:250
Period:250
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Aug 28, 2009 10:50 am     Reply with quote

This CCS example file shows how to measure a pulse by using the CCP.
Quote:
c:\program files\picc\examples\ex_ccpmp.c
fvnktion



Joined: 27 Jun 2006
Posts: 39

View user's profile Send private message

PostPosted: Fri Aug 28, 2009 11:28 am     Reply with quote

I have see the example and based this code off of it. The example talks about the overhead calculations as follows.

Quote:

// CCP_1 is the time the pulse went high
} // CCP_2 is the time the pulse went low
// pulse_width/(clock/4) is the time

// In order for this to work the ISR
// overhead must be less than the
// low time. For this program the
// overhead is 45 instructions. The
// low time must then be at least
// 9 us.


In my tested code I have followed these guidelines but am still missing an interrupt somehow. I would like to know why and what I can do to prevent it??
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group