![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
Guest
|
freq/phase measurement using multiple interrupts ...HELP! |
Posted: Tue Jul 27, 2004 4:11 pm |
|
|
Hello, I'm using CCP1 and CCP2 to determine the frequency and phase angle between two signals. Both signals have the same freq (range is 1-100Hz) but can vary in phase wrt each other. This looked like a fairly simple task using CCP1 and CCP2 in capture mode: time between CCP1 captures gives the freq, time between CCP1 and CCP2 gives the phase.
This program works 99% of the time but gives a wild answer every few minutes. The errors seem to result from a late TIMER1 overflow (maybe not late...but definetly out of place). A sample output is below, read as freq(Hz), phase(deg), period(inst cycles) and phase(inst cycles). First at 12Hz, 2.42 deg ...every thing is going fine, and then disaster... notice that the period jumps up by 65536!
Next at a phase angle of 4.46deg apparently only CCP2 gets knocked-off by 2^16.
...
12.00 2.42 416635 2808
12.00 2.42 416635 2808
12.00 2.42 416635 2808
10.36 51.02 482171 68343
14.24 2.87 351099 2807
12.00 2.42 416636 2808
...
12.00 4.46 416635 5167
12.00 4.46 416635 5167
12.00 -52.16 416635 -60369
12.00 4.46 416636 5168
12.00 4.46 416635 5168
So I *think* I know whats happening...I'm just not sure how to avoid it. Any help would really be appreciated. Below is the code. My original program does more things (LCD, alarms, etc) but I removed all that to show the core problem (in case you are wondering why 20MHz, etc). The prog below compiles (PCW 3.202) and runs resulting in the above output. I tried using INT_TIMER1 FAST, but got the same results. What am I doing wrong? Is there something simpler than writing my oun int handler? Thanks.
// *****************************************************
#include <16F876.h>
#device *=16
#fuses HS, NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP
#use delay(clock=20000000)
#use fast_io(C)
#priority timer1, ccp2, ccp1
#use rs232(baud=9600, xmit=PIN_C6)
// *****************************************************
signed int32 lastTime = 0, deltaTime = 0, period;
int16 overTime = 0;
int1 gotCCP1 = FALSE;
union{
int16 t[2]; // CCP1 capture timer - 32bits
int32 time;
} capture1;
union{
int16 t[2]; // CCP2 capture timer - 32bits
int32 time;
} capture2;
// *****************************************************
#INT_TIMER1
timer1_isr()
{ // OVERTIME - Incremented on Timer1 rollover to
overTime++; // increase timer resolution from 16 to 32 bits
}
// ******************************************************
#INT_CCP1
ccp1_isr()
{
capture1.t[1] = overTime;
capture1.t[0] = CCP_1;
period = capture1.time - lastTime;
lastTime = capture1.time;
deltaTime = capture1.time - capture2.time;
gotCCP1 = TRUE;
}
// ******************************************************
#INT_CCP2
ccp2_isr()
{
capture2.t[1] = overTime;
capture2.t[0] = CCP_2;
}
// ******************************************************
void main()
{
float freq, fperiod, phase, dTime;
float cnts2us = 5.0e6; // 1/(counts to microseconds) for 20MHz clock
char outMsg[40];
setup_ccp1(CCP_CAPTURE_RE); // CCP1 - rising edge
setup_ccp2(CCP_CAPTURE_RE); // CCP2 - rising edge
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);// Timer1 interrupt
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_CCP1);
enable_interrupts(INT_CCP2);
enable_interrupts(GLOBAL);
set_tris_C(0xAF); // All inputs except C4 and C6
while(TRUE) { // Start main program loop (endless)
while(!gotCCP1); // Wait for CCP1 interrupt
gotCCP1 = FALSE;
dTime = deltaTime;
fperiod = period;
freq = cnts2us / fperiod;
phase = (dTime / fperiod) * 360.0;
if (phase > 180.0) phase-=360.0; // Scale from 0-360 to +/-180
sprintf(outMsg,"%04.2f %04.2f %ld %ld\n\r",
freq,phase,period,deltaTime);
printf("%s",outMsg);
}
}
[/code] |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
![](templates/subSilver/images/spacer.gif) |
c_merk
Joined: 27 Jul 2004 Posts: 1
|
|
Posted: Thu Jul 29, 2004 8:43 am |
|
|
Thanks PCM...You the MAN!
I added the timer1 check (TMR1IF) per your suggestion in both CCP int routines and that seems to do the trick. It's been going hours without a glitch! Code fragment is below. The output did not become well-behaved until testing for 3(or less) MSB counts on the CCP_1 register ( ...capture1.d[1] <=3), which surprised me because that seems to be a long time for a short ISR. I do have three interrupts contending for attention ...perhaps that explains it.
Your help is really appreciated.
...
#INT_CCP1
ccp1_isr()
{
static int32 lastTime=0;
int16 overTCopy;
capture1.t[0] = CCP_1;
overTCopy = overTime;
if (TMR1IF) {
if ( capture1.d[1] <=3) overTCopy++;
overTime++;
TMR1IF = 0;
}
capture1.t[1] = overTCopy;
period = capture1.time - lastTime;
lastTime = capture1.time;
if ((deltaTime = capture1.time - capture2.time)>0) gotCCP1 = TRUE;
}
... |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|