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 support@ccsinfo.com

help me with clock calculation

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



Joined: 08 Feb 2009
Posts: 72
Location: campulung muscel

View user's profile Send private message Send e-mail Yahoo Messenger

help me with clock calculation
PostPosted: Fri Feb 13, 2009 9:29 am     Reply with quote

hello, I can help me with a calculated tachometru. Using a working frequency of 20Mhz. I want to use for an engine in 4 cylinders. But I forumula calculation for 2 or 3 cylinders.
How to calculate in my code?

Code:
#include "main.h"
#include "turometru.h"

int16 isr_ccp_delta;

#int_ccp1
void ccp1_isr(void)
{
int16 current_ccp;
static int16 old_ccp = 0;

// Read the 16-bit hardware CCP1 register
current_ccp = CCP_1;  // From 16F877.H file

// Calculate the time interval between the
// previous rising edge of the input waveform
// and the current rising edge.  Put the result
// in a global variable, which can be read by
// code in main().
isr_ccp_delta = current_ccp - old_ccp;

// Save the current ccp value for the next pass.
old_ccp = current_ccp;

}

void turometru(void) {
int16 current_ccp_delta;
int16 frequency;
// Setup Timer1 and CCP1 for Capture mode so that
// we can measure the input signal's frequency.
// The input signal comes from the CCP2 pin, which
// is connected to the CCP1 pin with a wire.
set_timer1(0);           
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
setup_ccp1(CCP_CAPTURE_RE);   

// Clear the CCP1 interrupt flag before we enable
// CCP1 interrupts, so that we don't get an unwanted
// immediate interrupt (which might happen).
clear_interrupt(INT_CCP1);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);

 //  while (1) {
     
      // Now calculate the frequency.

   // Get a local copy of the latest ccp delta from the isr.
   // We have to disable interrupts when we read a global
   // isr variable that is larger than a single byte.
   disable_interrupts(GLOBAL);
   current_ccp_delta = isr_ccp_delta;
   enable_interrupts(GLOBAL);

   // To calculate the frequency of the input signal,
   // we take the number of clocks that occurred
   // between two consecutive edges of the input signal,
   // and divide that value into the number of Timer1
   // clocks per second.   Since we're using a 4 MHz
   // crystal, the Timer1 clock is 1 MHz (Timer1 runs
   // at the instruction cycle rate, which is 1/4 of the
   // crystal frequency).  For example, suppose the
   // the input waveform has a frequency of 244 Hz.
   // 244 Hz has a period of about 4098 usec.
   // Timer1 is clocked at 1 MHz, so between two
   // consecutive rising edges of the input signal,
   // it will count up by 4098 clocks.  To find the
   // frequency, we divide 4098 into the number of
   // clocks that occur in 1 second, which is 1000000.
   // This gives 1000000 / 4098 = 244 Hz.
   
   frequency = (int16)(500000L / current_ccp_delta );
   frecventa = frequency ;
// Display the calculated frequency.
//lcd_gotoxy(1,1);   
//printf(lcd_putc,"%lu Hz\n\r", current_ccp);

   delay_ms(100);

  // }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Feb 13, 2009 1:50 pm     Reply with quote

Quote:

Using a working frequency of 20Mhz.

frequency = (int16)(500000L / current_ccp_delta );

You made a mistake. That number should be 20 MHz/4.
It should be: 5000000L
soulraven



Joined: 08 Feb 2009
Posts: 72
Location: campulung muscel

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Fri Feb 13, 2009 2:27 pm     Reply with quote

thx, I saw the mistake after more digging.
now try the code below, works in the first, maybe that is another 32bit resolution on timer1. But if you mean using the formula tachometru
frequency = (frequency * 60) / 2;
below 50Hz is a drifting of 10rpm
why?
I saw in the forum, a reference to an ASM code to increase execution brave, how can I adapt to my code?
Code:
disable_interrupts (GLOBAL);
    current_ccp_delta = g32_ccp_delta;
    enable_interrupts (GLOBAL);


Code:

#include "main.h"
#include "turometru.h"

#priority CCP1, TIMER1

#define BytePtr(var, offset)   (char *)(&(char *)var + offset)

#byte PIR1 = 0xF9E
#bit  TMR1IF = PIR1.0

int8  gc_timer1_extension = 0;
int8  gc_capture_flag = FALSE;
int32 g32_ccp_delta;

//------------------------------------------------------
#int_timer1
void timer1_isr(void)
{
gc_timer1_extension++;
}

//------------------------------------------------------

#int_ccp1
void ccp1_isr(void)
{
char timer_ext_copy;
int32 current_ccp;
static int32 old_ccp = 0;

gc_capture_flag = TRUE;       

current_ccp = (int32)CCP_1;   

// Get local copy of the timer ext.
timer_ext_copy = gc_timer1_extension;


if(TMR1IF)
  {
   if(*BytePtr(current_ccp, 1) < 2)  // Was CCP captured after Timer1 wrapped?
      timer_ext_copy++;  // If so, inc the copy of the timer ext.

   // Since we know a timer interrupt is pending, let's just
   // handle it here and now.  That saves a little load off
   // the processor.
   gc_timer1_extension++;  // Increment the real timer extension
   TMR1IF = 0;     // Then clear the Timer1 interrupt
  }

// Insert the timer extension into the proper place in the 32-bit
// CCP value.
// ie.,  Insert it into location "EE" as follows: 0x00EEnnnn
// (nnnn = the CCP).
*BytePtr(current_ccp, 2) = timer_ext_copy;

g32_ccp_delta = (current_ccp > old_ccp) ? current_ccp - old_ccp : current_ccp + (0x1000000 - old_ccp);

// Save the current ccp value for next time.
old_ccp = current_ccp;

}

//=======================
void turometru()
{
int16 frequency;
int32 current_ccp_delta;

set_timer1(0);           
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);   
setup_ccp1(CCP_CAPTURE_RE);   

// Enable interrupts.
clear_interrupt(INT_TIMER1);
enable_interrupts(INT_TIMER1);

clear_interrupt(INT_CCP1);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);

//while(1)
//  {
   disable_interrupts(GLOBAL);
   current_ccp_delta = g32_ccp_delta;;
   enable_interrupts(GLOBAL);

   if(gc_capture_flag == TRUE)
     {
   frequency = (int16)((5000000L + (current_ccp_delta >> 1)) / current_ccp_delta);
   frecventa = (frequency * 60)/2;
   lcd_gotoxy(5,1);
     printf(lcd_putc,"%lu\n", frecventa);
     // printf(lcd_putc,"%lu Hz, delta = %lx \n\r", frequency, current_ccp_delta);

      gc_capture_flag = FALSE;
    }
  else
    {
lcd_gotoxy(5,1);
     printf(lcd_putc,"0   \n");
    }

  delay_ms(120);
 //}

}


thanks much PCM programmer, I saw that you were very prompt and want to help beginers
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