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

long division

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



Joined: 13 Jun 2009
Posts: 6

View user's profile Send private message

long division
PostPosted: Sat Jun 13, 2009 4:57 pm     Reply with quote

Hi, I'm a new member

I wrote my project code using capture command to find the time between two positive edge of square pulses. I declared long type parameter to represent the difference between two times that have been captured, but I can't calculate the parameters inverted (1/parameter), it always gives zero.

Here is my code
Code:

#include <16F877.h>
#include <STDLIB.H>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

int1 flag;
long rise1,rise2,period, rate;

#int_ccp1
void isr()
{
if (flag==0)
{
   rise1 = CCP_1;
   flag=1;
}
else

if (flag==1)
{
   rise2 = CCP_1;
   period=rise2-rise1;
   flag=0;

}

}



void main()
{
   flag=0;

   setup_ccp1(CCP_CAPTURE_RE);    // Configure CCP1 to capture rise
   setup_timer_1(T1_INTERNAL);    // Start timer 1

   enable_interrupts(INT_CCP1);   // Setup interrupt on risining edge
   enable_interrupts(GLOBAL);

   while(TRUE) {
     delay_ms(1000);
   printf("\r period in us is %lu  ", period);
  // rate = 1 / period ;
  //  rate = ldiv(1, period);
  //   printf("\r rate is us %lu  ", rate);

   }
}

I used ex_CCPMP.c to help me in writing my code.
Thanks.
asseel



Joined: 13 Jun 2009
Posts: 6

View user's profile Send private message

PostPosted: Sat Jun 13, 2009 6:37 pm     Reply with quote

hi its me again
I solve the previous problem by divide 1000000 over the parameter(1000000/parameter => "the result was very small so give0"and because the measured time is in us)
but now I have another problem that at low frequencies (below 15HZ) the calculation of the frequency (1/period) is incorrect.

Note:
I use 4MHz clock.
Period =difference between two captured time.

Please help me as soon as possible Shocked
Thanks
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sun Jun 14, 2009 12:33 am     Reply with quote

Yes, it's 16 Bit integer arithmetic, not a pocket calculater utilizing float numbers.

A 1 us period measurement has a range of 65.535 ms respectively 15.26 Hz. The range must be extended to measure lower frequencies. Because the used PIC has only 16 Bit timers, it's a bit complicated, involving e.g. a timer interrupt and a counter for period high word. A special issue results from the possibility of a timer captured after an overflow that hasn't been yet counted in the timer interrupt.

As another comment, rate must be of int32 type to give always correct results in your division. Long is int16 by default in CCS C.
asseel



Joined: 13 Jun 2009
Posts: 6

View user's profile Send private message

PostPosted: Sun Jun 14, 2009 8:18 am     Reply with quote

Quote:

The range must be extended to measure lower frequencies


That supposed to minimize the delay (clock), or what?
How can I do that?
I try to minimize it to 2Mhz and the program works correct up to 7 Hz, with need to divide by 2 each time.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sun Jun 14, 2009 11:19 am     Reply with quote

You should clarify your measurement specification, in case of frequency measurement intended range and resolution. I simply assumed that you want to keep the 1 µs period resolution but extend the period range above 65 ms. Then you have to count timer overflows and process the counter in the period and frequency calculation.
asseel



Joined: 13 Jun 2009
Posts: 6

View user's profile Send private message

PostPosted: Sun Jun 14, 2009 2:17 pm     Reply with quote

thank you FvM

unfortunately I'm not expert and can not understand every thing you state above, i do search in this forum and i found this post:

http://www.ccsinfo.com/forum/viewtopic.php?t=906

its seem such as my problem, the timer overflowed before the CCP1 interrupt occur, so i have readings (for small frequencies < 2 Hz) give wrong captured values .

i understand from your talk that i have to extend timer 1 to 24 bit timer to avoid this problem, and i try to use the PCM programmer code here:

Code:


//------------------------------------------------------------
// MACROS
// This macro allows us to insert a byte into the specified
// offset of a 16 or 32 bit variable. Example:
// *BytePtr(temp_long, 2) = 0x55;
// If temp_long is 0, the above line will make it become:
// 0x00550000
#define BytePtr(var, offset) (char *)(&var + offset)

// The Timer1 interrupt increments an 8-bit variable which
// extends the timer to 24 bits. We need this so we can
// avoid having to switch the Timer pre-scaler between "low"
// and "high" rpm ranges.

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

//------------------------------------------------------
// When we get a CCP interrupt, read the CCP register and
// save it in a global variable.

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

// Set flag to indicate that we did a capture.
gc_capture_flag = TRUE;

current_ccp = (int32)CCPR1_REG; // Read the current CCP

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

// Check if a Timer1 interrupt is pending. If so, check if
// the CCP capture occurred before or after the Timer rolled
// over. We can tell if it occurred after it rolled over, if
// the CCP's MSB is zero. ie., if the CCP is somewhere between
// 0x0000 and 0x00FF.
// We know that we can just check if the MSB = 0x00, because
// it takes about 30 us to get into this ISR. (Using a 4 Mhz
// crystal on a 16F628). The timer increments at 1 us per
// count, so 0xFF = 255 us.
// Actually, to be safer, I'll give it 2 MSB counts, which is
// 511 us. That way, if I lengthen any of the other ISR's,
// we'll still be able to detect the roll-over OK.
// If the timer did roll over after we got a CCP interrupt,
// then we need to increment the timer extension byte, that we
// save. We have to do that because the CCP interrupt has
// priority, and so it executes before the Timer isr can
// execute and increment the extension.
// (Designing the code with the priority switched doesn't help.
// You still have the same type of problem. With CCP first,
// the fix is easier).
//

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

// 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_BIT = 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;

// Because we're using unsigned math, we don't have to worry
// if the current value is less than the old. The result is
// always the absolute value of the difference. The only way
// there could be a problem is if the new CCP value had rolled
// over twice. But with a 24-bit value, and a Timer
// pre-scalar of 1, that's 16.7 seconds. That's way beyond any
// practical value.

// Edited on Jan. 2, 2004: There was a bug in this routine,
// because I was promoting a 24-bit value to a 32-bit data type,
// but the upper byte was always left = 0. This caused a problem
// with the 32-bit subtraction when the 24-bit value rolled over past 0.
// Kenny spotted this error and provided a fix in a PM to me.
// I have commented out the original line, and inserted his fix, below.
//g32_ccp_delta = current_ccp - old_ccp;
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;

}


but many errors occur, i have lack of understanding of this criteria and i don't know how to use it.


my code again:

Code:


#include <16F877.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay (clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
     
int1 flag,f;
long rise1,rise2,period,frq,in;
int32 rate;
int8 count;


#int_ccp1
void isr()
{

if (flag==0)
{
   rise1 = CCP_1;
   flag=1;
}
else

if (flag==1)
{
   rise2 = CCP_1;
   period=rise2-rise1;

   flag=0;
}
}


void main()
{
   flag=0;
   f=0;
   count=0;
   setup_ccp1(CCP_CAPTURE_RE);    // Configure CCP1 to capture rise
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);   // Start timer 1

   enable_interrupts(INT_CCP1);   // Setup interrupt on risining edge
   enable_interrupts(GLOBAL);

   while(TRUE) {
   delay_ms(1000);
   printf("\r period in us is %lu  ", period);
   rate =125000/period;
   printf("\r rate is %lu  ", rate);
 
   }//while
}//main



i try to translate it onto:


Code:


#include <16F877a.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay (clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#define Byteptr(var,offset)(char *) (&var +offset)

int1 flag, cap_flag;
long rise1,rise2,period;
int32 rate;
int count;

#int_ccp1
void ccp1_isr()
{

/*char timer_ext_copy;
int32 current_ccp;
static int32 old_ccp=0;

cap_flag=1;
current_ccp= (int32)CCPR1_REG;
timer_ext_copy= count;

if (TMR1IF_BIT)
{
if(*Byteptr(current_ccp,1)<2)
timer_ext_copy++;
count++;
TMR1IF_BIT=0;
}//if (TMR1IF_BIT)

*Byteptr(current_ccp,2)=timer_ext_copy;
g32_ccp_delta= (current_ccp> old_ccp)? current_ccp - old_ccp : current_ccp+(0x10000000 - old_ccp);
*/
if (flag==0)
{
   rise1 = CCP_1;
   flag=1;
}
else

if (flag==1)
{
   rise2 = CCP_1;
   period=rise2-rise1;

   flag=0;
}

}

/*
#INT_TIMER1
void timer1_isr()
{
count++;
}

*/

void main()
{
   flag=0;
   count=0;
   setup_ccp1(CCP_CAPTURE_RE);    // Configure CCP1 to capture rise
   setup_ccp2(CCP_CAPTURE_FE);

   setup_timer_1(T1_INTERNAL);    // Start timer 1

   enable_interrupts(INT_CCP1);   // Setup interrupt on risining edge
   enable_interrupts(GLOBAL);

   while(TRUE) {
   delay_ms(1000);
   printf("\r period in us is %lu  ", period);

   rate =1000000/period;
   printf("\r rate is %lu  ", rate);

   }
}


errors like :
Quote:
undefined identifier CCPR1_REG
appear
i know maybe this seem stupid a bit Embarassed Embarassed
thank you
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