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

Timing problems betwee two interrupts ?

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



Joined: 12 Jul 2005
Posts: 49

View user's profile Send private message

Timing problems betwee two interrupts ?
PostPosted: Thu Aug 25, 2005 4:45 pm     Reply with quote

Hello,

As I am still newbie, I can't directly find why my blue led is not flickering at a constant interval.
It blinks about 3 (or 6 or 9 or 10) times correct and than it give a long (not 100 ms but about 1 sec) blink. This repeats.

Is this somewere a confusion between the two interrupt routines ?

Thanks.

PS : some people will recognise parts of the code. Smile

Code:
#include <16F877.h>
#fuses HS, NOWDT, NOPROTECT
#use delay(clock=20000000)
#use rs232(baud=4800, xmit=PIN_B1, rcv=PIN_B0,stream=GPS)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7,stream=MODEM)

#define GPS_BUFFER_SIZE 70
#define MSEC_500   (76)  // 20.000.000/(4*128*256) per sec /2
#define MSEC_100   (15)
#define LED_BLUE   PIN_A0
#define LED_GREEN  PIN_A1
#define LED_RED    PIN_A2

static char    GPS_buffer[GPS_BUFFER_SIZE];
static char    GPS_code[]  = "$GPRMC";
static char*   GPS_p       = GPS_buffer;
static int     GPS_state   = 0;
static short   GPS_done    = TRUE;
static short   GPS_found   = FALSE;

int8     BLINK_RATE, counter, ON_TIME;
int1     system_on;


#INT_RTCC
clock_isr() {
if(system_on)
      {
      counter++;
      if (counter == BLINK_RATE) {output_high(LED_BLUE);}
      if (counter == ON_TIME) {output_low(LED_BLUE);
      counter = 0;}
      }
}


#int_ext
void GPS_isr()
{
   char c;
   c = fgetc(GPS);
   if( GPS_found == FALSE )   {  GPS_found = TRUE;   }
   if( GPS_state < 6 )
   {
      if( c == GPS_code[GPS_state] )
      {
         if( GPS_state == 0 ) {  GPS_p = GPS_buffer;  }
         *GPS_p = c;
         GPS_p++;
         GPS_state++;
      }
      else      { GPS_state = 0; }
   }
   else
   {
      if( c == 0x0d )   // carriage return
      {
         *GPS_p = 0;
         GPS_done = TRUE;
         disable_interrupts(INT_EXT);
      }
      else
      {
         *GPS_p = c;
         GPS_p++;
         GPS_state++;
      }
   }
}

main()
{
counter =0;
system_on =1;
BLINK_RATE=MSEC_500 * 2;
ON_TIME=BLINK_RATE + MSEC_100;

   // initialise INTERRUPTS
   set_rtcc(0);
   setup_counters(RTCC_INTERNAL, RTCC_DIV_128);
   enable_interrupts(INT_RTCC);
   ext_int_edge(H_TO_L);
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);

   // Version output to MODEM (= PC with Hyperterminal)
   fprintf(MODEM," PIC Online\n\r");
   fprintf(MODEM," Version : 0.0.4\n\r");
   fprintf(MODEM," Copyright 2005 Bart De Pauw\n\r");
   fprintf(MODEM,"\n\r");

   while(TRUE)
   {
      if( GPS_found && GPS_done )
      {
         fputs(GPS_buffer,MODEM); // <= gps string at ones to MODEM.

         // split GPS string in separate fields
         // to program

         // Output obtained fields to MODEM stream.
         // fprintf(MODEM,"Date : \n\r");
         // fprintf(MODEM,"Time : \n\r");
         // fprintf(MODEM,"Speed : \n\r");
         // fprintf(MODEM,"Heading : \n\r");
         // fprintf(MODEM,"Lat : \n\r");
         // fprintf(MODEM,"Lon : \n\r");
         // fprintf(MODEM,"Fix : \n\r");
         // fprintf(MODEM,"Satelites used : \n\r");
         // fprintf(MODEM," : \n\r");
         // fprintf(\n\r");
         GPS_state = 0;
         GPS_done = FALSE;
         enable_interrupts(INT_EXT);
      }
   }
}
// ---------------------------------------------------------

_________________
I like Skype (www.skype.com), my username is BplotM
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Aug 26, 2005 9:16 am     Reply with quote

The routine for blinking the led looks fine to me, so I guess the error is in the other interrupt.
Interrupt routines should be as fast as possible, never implement any blocking function calls in an interrupt routine. Once an interrupt routine is active it will prohibit other interrupts from executing.
In your external interrupt routine you are calling fgetc() which is a potential blocking function, if no data is available it will wait for a character to arrive.

What is connected to your external interrupt line?
Is it possible for you to use the serial receive (INT_RX) instead?
Bart



Joined: 12 Jul 2005
Posts: 49

View user's profile Send private message

PostPosted: Fri Aug 26, 2005 2:41 pm     Reply with quote

( Bedankt ckielstra voor de reactie ! )

To the external interrupt line there is a serial GPS connected with generate a interrupt when the data string comes in. So, normally, as I detect the start off the string with the interrupt, the fgetc() never has to wait. (String is about 70 characters long).

The only I can thing is that it stays to long in that interupt routine for putting the string in the buffer. As you say, a new interrupt will not start before the previous is finished, I thing I am missing some blinking interupts.

Can someone confirm this ? Is there a solution ?
Thanks.
_________________
I like Skype (www.skype.com), my username is BplotM
Ttelmah
Guest







PostPosted: Fri Aug 26, 2005 3:04 pm     Reply with quote

One thing that would make things go really screwy, would be if there is an edge seen on the interrupt, and this is not the leading edge of a byte (noise, or a repeated trigger from the tail of the last byte received). In this case, the system will hang at the fgetc. Though it involves a couple of extra instructions, I'd add a test that the signal line is low, before calling fgetc, and return if not. It might fix the problem.
One problem, might be the case that the system is in the timer interrupt, when the external interrupt occurs. The typical interrupt 'latency' is about 25 instructions. so if a timer interrupt occured just at the same moment as a external interrupt, given that it has priority (this is implicit in the handler being first), then you will have the 25 instructions into the routine, the routine itself (perhaps another 20 instructions), plus the return time (about 20 instructions), plus about 28 instructions to get into the external interrupt code. This gives a worst case of about 93 instructions from the moment the interrupt occurs, to actually arriving at the fgetc routine. This then checks the signal for being low. This should be true (about 20uSec after the edge), but the time involved might make it unreliable. You can reduce this time, by giving the external interrupt priority over the LED code. Either move it's routine in front of the RTCC code, or use the 'priority' statement to define this as the higher priority routine. though it seems 'odd' to raise the priority of the interrupt that is not giving the problem, it might help.
So, I'd try testing for the start bit, and reversing the interrupt priority.

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