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

Problem with hardware interrupt and GPS

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



Joined: 08 Jul 2005
Posts: 91

View user's profile Send private message

Problem with hardware interrupt and GPS
PostPosted: Thu Apr 06, 2006 2:34 pm     Reply with quote

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);

      }

   }
}
sjbaxter



Joined: 26 Jan 2006
Posts: 141
Location: Cheshire, UK

View user's profile Send private message Visit poster's website

PostPosted: Thu Apr 06, 2006 2:50 pm     Reply with quote

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.
Ttelmah
Guest







PostPosted: Thu Apr 06, 2006 3:02 pm     Reply with quote

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
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