![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
weg22
Joined: 08 Jul 2005 Posts: 91
|
Problem with hardware interrupt and GPS |
Posted: Thu Apr 06, 2006 2:34 pm |
|
|
Hi all,
I know GPS topics are posted a lot here, but my question is not regarding how to read in a GPS string. I have combined 2 pieces of code below to:
(a) read in GPRMC and GPGSV data
(b) trigger a hardware interrupt when PIN_B0 goes high in order to read the length of a PWM signal
Both (a) and (b) work independently of each other. However, when I combine them, it gets through 1 or 2 cycles and then gets stuck somewhere in the "else" condition because the LED is constantly on. My guess is that either (a) the interrupt is occuring when the GPS data string is coming in once every two seconds which would then cause it to get stuck in one of the "while(GPR..!=1)" loops (but I disable the interrupts so this shouldn't be the case) or (b) the interrupt doesn't have time to occur before being disabled which means that when my "pulseLength" is > 3750 it will never recognize it (but this shouldn't be the case either because I am forcing the interrupt to occur at the end of the "else" loop (i.e. with variable forceInt). If anyone can help debug what's going on, I would really appreciate it!!
Thanks in advance,
weg
Code: |
#include <16F87.H>
#include <stdlib.h>
#include <math.h>
#define LED PIN_A2
#fuses HS,NOWDT,NOPROTECT,PUT,NOLVP
#use delay(clock=10000000)
#use rs232(baud=4800, xmit=PIN_A1, rcv=PIN_A0, stream=GPS)
// global variables
long pulseLength=0;
int forceInt=0;
// hardware interrupt to detect manual override
#int_ccp1
void isr()
{
set_timer1(0);
while(input(PIN_B0));
pulseLength = get_timer1();
forceInt=1;
}
main()
{
char c1, c2, c3, c4, c5, c6, c7, c8;
char c1a, c2a, c3a, c4a, c5a, c6a, c7a, c8a;
int GPRMC, GPRMB;
char tr1[10], wp1[10];
int j=0, k=0, n=0, commas=0;
long trueHeading=0, wayptHeading=0;
// setup interrupts
setup_ccp1(CCP_CAPTURE_RE); // on rising edge
setup_timer_1(T1_INTERNAL);
// enable interrupts
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);
output_high(LED); delay_ms(1500);
output_low(LED); delay_ms(1500);
while(1)
{
// check for manual override
if(pulseLength>3750) // pulseLength/(clock/4) is time in us (3750=1500us=1.5ms)
{
output_low(LED); // LED off under manual control
}
else
{
output_high(LED);
// clear variables
GPRMC=0;
GPRMB=0;
n=0;
for(n=0; n<10; n++)
{
tr1[n] = 0;
wp1[n] = 0;
}
c1 = c2 = c3 = c4 = c5 = c6 = c7 = c8 = 0;
c1a = c2a = c3a = c4a = c5a = c6a = c7a = c8a = 0;
trueHeading = 0;
wayptHeading = 0;
disable_interrupts(GLOBAL);
disable_interrupts(INT_CCP1);
forceInt=0;
//$GPRMC
while(GPRMC!=1)
{
c1 = fgetc(GPS);
if(c1=='$')
{
c2 = fgetc(GPS);
if(c2=='G')
{
c3 = fgetc(GPS);
if(c3=='P')
{
c4 = fgetc(GPS);
if(c4=='R')
{
c5 = fgetc(GPS);
if(c5=='M')
{
c6 = fgetc(GPS);
if(c6=='C')
{
commas=0;
while(commas!=10) // should be 8
{
c7 = fgetc(GPS);
if(c7==',') commas++;
}
j=0;
while(j<10)
{
c8 = fgetc(GPS);
if(c8==',') j=11;
else {tr1[j] = c8; j++;}
}
GPRMC=1;
}
}
}
}
}
}
}
//$GPRMB
while(GPRMB!=1)
{
c1a = fgetc(GPS);
if(c1a=='$')
{
c2a = fgetc(GPS);
if(c2a=='G')
{
c3a = fgetc(GPS);
if(c3a=='P')
{
c4a = fgetc(GPS);
if(c4a=='G')
{
c5a = fgetc(GPS);
if(c5a=='S')
{
c6a = fgetc(GPS);
if(c6a=='V')
{
commas=0;
while(commas!=1) // should be 11
{
c7a = fgetc(GPS);
if(c7a==',') commas++;
}
k=0;
while(k<10)
{
c8a = fgetc(GPS);
if(c8a==',') k=11;
else {wp1[k] = c8a; k++;}
}
GPRMB=1;
}
}
}
}
}
}
}
//enable_interrupts(INT_TIMER0);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);
trueHeading = atol(tr1);
wayptHeading = atol(wp1);
while(forceInt!=1);
//fprintf(PC, "tr1: %ld\n\r", trueHeading);
//fprintf(PC, "wp1: %ld\r\n", wayptHeading);
}
}
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
sjbaxter
Joined: 26 Jan 2006 Posts: 141 Location: Cheshire, UK
|
|
Posted: Thu Apr 06, 2006 2:50 pm |
|
|
First, read other threads on gps capture (i.e. use a circular buffer or state machine capturing gps info using int_rda interrupts.). That way you won't be disabling any interrupts and you CCP interrupts won't get ignored or missed !!!
You need to learn how to capture hardware activities in 'parallel', not just one at a time.
Also consider what happens to your program execution, as you currently have it, if you stop your gps serial input !!! as it is you program will just sit there waiting for something to happen (with interrupts disabled). Get the gps bit right and your CCP stuff will work. Also don't assume when parsing gps sentences that all the information is where you 'think' it should be. calculate the checksum for the data you get and compare it with the checksum privided at the end of the sentence. _________________ Regards,
Simon. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Thu Apr 06, 2006 3:02 pm |
|
|
A couple of comments.
Don't reset the timer when you enter the interrupt. Several uSec will already have passed, and this will make your value inaccurate. The CCP event, will have latched the timer value into the CCP registers, so if you wait for the other edge, then read the timer, and subtract the value in the CCP registers, you will get the accurate 'time'.
Remember also, that disabling the interrupts, does not stop the interrupt flag from being set. It will have almost certainly been set in the long delay handling the serial, and you will then jump into the interrupt handler, without a pulse actually being present. Just disable the global flag, and clear the INT_CCP flag, before re-enabling this.
Though not a problem, you don't need a seperate value for each received character. Use the same one for each character in turn. You also don't need to waste time clearing the variables, since they are always 'written' by the fgetc function.
You can also use the same variable for both counters (i and j).
Now one possibility for the problem, is that once the pulse width has been measured, you arrive at the serial handler 'out of sync' (in the middle of a character), and then depending on the nature of the incoming serial, you may have problems re-synchronising. Try waiting for the serial line to be 'high' for at least one character time, before re-entering the serial handler.
Best Wishes |
|
![](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
|