|
|
View previous topic :: View next topic |
Author |
Message |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Aug 20, 2009 5:33 pm |
|
|
What is your compiler version ? I don't think you ever posted it. |
|
|
nizar445
Joined: 09 Jun 2009 Posts: 23
|
|
Posted: Thu Aug 20, 2009 6:04 pm |
|
|
Quote: | What is your compiler version ? |
MPLAB 8.10
CCS C Compiler V4.013 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Aug 20, 2009 6:13 pm |
|
|
Post the program you're actually using to test this.
You referred to some earlier program. I looked earlier in the thread.
The one I found is doing compares and lighting up LEDs. That's useless
to me for a test program. I need one that displays the frequency
on a terminal window. Then I can test your problem.
-------
I can't do anything more on this today. I'll work on it tomorrow. |
|
|
nizar445
Joined: 09 Jun 2009 Posts: 23
|
|
Posted: Thu Aug 20, 2009 7:07 pm |
|
|
Here is my full code:
Code: | #include <16F87.H>
#fuses NOPROTECT, NOLVP, NOPUT, NOMCLR,NOBROWNOUT, NOCPD, NOWRT, NODEBUG, XT, NOWDT
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_B5)
// This global variable holds the time interval
// between two consecutive rising edges of the
// input signal.
float isr_ccp_delta;
// When a rising edge occurs on the input signal,
// the CCP1 will 'capture' the value of Timer1
// at that moment. Shortly after that, a CCP1
// interrupt is generated and the following isr
// is called. In the isr, we read the 'captured'
// value of Timer1. We then subtract from it the
// Timer1 value that we 'captured' in the previous
// interrupt. The result is the time interval
// between two rising edges of the input signal.
// This time interval is then converted to a frequency
// value by code in main().
#int_ccp1
void ccp1_isr(void)
{
float current_ccp;
static float old_ccp = 0;
current_ccp = CCP_1; // From 16F819.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 main()
{
float current_ccp_delta;
float frequency;
// Setup Timer1 and CCP1 for Capture mode so that
// we can measure the input signal's frequency.
// The input signal comes from an external function
// generator, which is connected to the CCP1 pin 8 with a wire.
set_timer1(0);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
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);
output_high(PIN_B4);
delay_ms(1000);
while(1)
{
while(1)
{
// 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
// internal clock, the Timer1 clock is 1 MHz (Timer1 runs
// at the instruction cycle rate, which is 1/4 of the
// internal clock 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 = (float)(125000L / current_ccp_delta);
// Display the calculated frequency.
printf("\n\r freq = %f", frequency);
if (frequency <= 30)
{
printf("low");
output_low(PIN_B4);
delay_ms(3000);
output_high(PIN_B4);
delay_ms(3000);
}
else if (frequency > 30 && frequency <= 59)
{
printf("normal");
output_low(PIN_B4);
delay_ms(1000);
output_high(PIN_B4);
delay_ms(1000);
}
else
{
printf("high");
output_low(PIN_B4);
delay_ms(500);
output_high(PIN_B4);
delay_ms(500);
break;
}
} // end first while 1
while(1)
{
disable_interrupts(GLOBAL);
current_ccp_delta = isr_ccp_delta;
enable_interrupts(GLOBAL);
frequency = (float)(125000L / current_ccp_delta);
printf("\n\r freq = %f", frequency);
delay_ms(1000);
if (frequency > 59)
{
output_low(PIN_B4); //LED ON (active LOW)
printf("hiiiiiiiiiigh");
delay_ms(1000);
// read analoge input and reduce input code goes here to be develped later!!
}
else if (frequency <= 59)
{
printf("good bye");
delay_ms(1000);
break;
}
}// end second while 1
} //end while(1)
} // end main |
Thanks a lot mate |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Aug 21, 2009 12:41 pm |
|
|
Quote: | float isr_ccp_delta;
#int_ccp1
void ccp1_isr(void)
{
float current_ccp;
static float old_ccp = 0;
.
.
.
}
void main()
{
float current_ccp_delta;
float frequency; |
You have edited my code. Did you realize this ? The data types
for the variables shown in bold are supposed to be 'int16'. That's what
they were. If you change them back to int16 then it all starts working.
There is nothing wrong with my code (a little bit of pride at work here). |
|
|
nizar445
Joined: 09 Jun 2009 Posts: 23
|
|
Posted: Fri Aug 21, 2009 3:54 pm |
|
|
Yes I did that on purpose, I thought that, by changing all the variables to “float” I will get more accurate readings as all the calculations will include the decimals!!?
If I change these variables back to “int16” will I get the decimals?
Thanks for your reply. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Aug 21, 2009 4:10 pm |
|
|
To get a fractional result, with numbers to the right of the decimal point,
do this:
1. Change all the specified data types back to 'int16', as I indicated in
my earlier post. (and no others).
2. Change the equation that calculates the frequency to this:
Code: | frequency = 125000.0 / current_ccp_delta; |
Note how the numerator is now represented as a float value, by
appending a .0 on the end of it. This forces the compiler to do
the equation with floating point math, and to give a floating point
result. |
|
|
nizar445
Joined: 09 Jun 2009 Posts: 23
|
|
Posted: Fri Aug 21, 2009 5:07 pm |
|
|
Thanks for your reply, I will try that, by the way, there was “L” letter next to the 125000 in the frequency formula do I need to include it or not?
Code: | frequency = (125000L / current_ccp_delta); |
And why did you put it in your program, and what does it do? |
|
|
|
|
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
|