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 CCS Technical Support

RDA_isr() failed to re-enabled

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



Joined: 17 Apr 2013
Posts: 3

View user's profile Send private message

RDA_isr() failed to re-enabled
PostPosted: Wed Aug 27, 2014 6:54 am     Reply with quote

Hello,

I use a pic18f458 to receive GPS NMEA data, since it takes a period of time to solve the packet in while-loop, the RDA_isr() is disabled whenever the buffer is full. It is until the packet solved, while-loop re-enables the RDA_isr(). But, according to the test, I just get the first packet and solved. Never receiving the others. I guess the problem is that the RDA_isr is not in service anymore. But, how can I re-enable it successfully?

Thank you.

Code:
#include  <18f458.h>
#include  <stdlib.h>
#fuses    HS,WDT1
#use      delay(clock = 20000000)
#use      rs232(baud = 9600, xmit = PIN_C6, rcv = PIN_C7)
#define   Length 128

int8 gpsMTK1[Length],gMTK1_i=0,len=0,tmp_MTK1[3]={0,0,0},RDA_buf=0;
int8 flg_MTK1=0,data_MTK1=0,no_MTK1=0;
int8 time_hh[2],time_mm[2],time_ss[2];
int8 Latd_MTK1[20],Latm_MTK1[20],Lond_MTK1[20],Lonm_MTK1[20];
int8 n;


#INT_RDA
void RDA_isr(void)
{

  if(RDA_buf == 0)
  {
    gpsMTK1[len] = getc();
   
    len++;
   
    if(len >= 128)
    {
      RDA_buf = 1;
     
     
      printf("%c",'Q');
      len = 0;
      disable_interrupts(INT_RDA);
      disable_interrupts(GLOBAL);
    }
  }
}


void main()

  for(n=0;n<128;n++)  gpsMTK1[n]=0;
   
 
  enable_interrupts(INT_RDA);
  enable_interrupts(GLOBAL);
       
  while(TRUE)
  {   
    if(RDA_buf == 1)
    {   
      for(gMTK1_i = 0 ; gMTK1_i < Length ; gMTK1_i++)
      {
        tmp_MTK1[0] = tmp_MTK1[1];
        tmp_MTK1[1] = tmp_MTK1[2];
        tmp_MTK1[2] = gpsMTK1[gMTK1_i];
       
   
          if(tmp_MTK1[0]=='G' && tmp_MTK1[1]=='A' && tmp_MTK1[2]==',')
          {
            flg_MTK1 = 1;
            data_MTK1 = 0;
            no_MTK1 = 0;         
          }
     
          else if(tmp_MTK1[2]!='*' && flg_MTK1==1)
          {
            if(tmp_MTK1[2]!=',')
              {
                if(data_MTK1 == 0)
                  {
                    if(no_MTK1<=1)  time_hh[no_MTK1] = tmp_MTK1[2];
                    else if(no_MTK1>=2 && no_MTK1<=3) time_mm[no_MTK1-2] = tmp_MTK1[2];
                    else if(no_MTK1>=4 && no_MTK1<=5) time_ss[no_MTK1-4] = tmp_MTK1[2];
                   
                  }
               
                else if(data_MTK1 == 1)
                  {
                    if(no_MTK1<=1)  Latd_MTK1[no_MTK1] = tmp_MTK1[2];
                    else if(no_MTK1>=2 && no_MTK1<=9)  Latm_MTK1[no_MTK1-2] = tmp_MTK1[2];
                   
                  }
                else if(data_MTK1 == 3)
                  {
                    if(no_MTK1 <= 2)  Lond_MTK1[no_MTK1] = tmp_MTK1[2];
                    else if(no_MTK1>=3 && no_MTK1<=9)  Lonm_MTK1[no_MTK1-3] = tmp_MTK1[2];
                   }
             no_MTK1++;
              }
            else
              {
              no_MTK1 = 0;
              data_MTK1++ ;
              }
          } // else if(tmp_MTK1[2]!='*' && flg_MTK1==1)
       } // for-loop
       RDA_buf = 0;
       flg_MTK1 = 0;
       
    enable_interrupts(INT_RDA);
    enable_interrupts(GLOBAL);
 
    printf("%c",'P');
   
    } //if(RDA_buf == 1)
       
  } // while-loop
} // void main()
temtronic



Joined: 01 Jul 2010
Posts: 9245
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Aug 27, 2014 7:44 am     Reply with quote

couple of points..
1) it is NEVER a good idea to have a printf(..) inside any ISR..
2) CCS disables the called ISR, so you don't have to...
3)Do you get the 'P' printed out just after the enable ISRs ????

if not,then I think your if..loops might be wrong.
A quick easy test would be to just collect the 128 bytes of data,maybe send them to the PC. Forget about the 'parsing' algorithms until you call receive and display the GPS data string.

It's easier to debug smaller programs !

hth
jay
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Wed Aug 27, 2014 7:47 am     Reply with quote

hi,

The *best* answer is to never disable the int_rda interrupt! Instead, use a interrupt driven circular buffer to receive the NMEA data from the GPS. This technique is illustrated in example program 'ex_sisr.c'.

You also need to add 'Errors' to your #use rs232 declaration. At the moment, it is likely that your hardware UART is overflowing before you have a chance to diasble it, and is locking up. That is why you only receive the 1st NMEA sentence, and then nothing more.

Again, your method is a bit flawed, so check out that example program I mentioned!

John
Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Thu Aug 28, 2014 12:51 am     Reply with quote

As an 'add on' to what has already been said, if you absolutely 'must' use the current approach (though it is very much 'not' the way to do things...), the safe way to work, is to set a single bit flag, when you want the data to be ignored, and in the ISR, simply read the character, then if the flag is set 'throw it away'.

The key problem is to understand that the interrupt says 'there is a character waiting, that wants to be read'. Disabling the interrupt stops this read being done, and after just one more character arrives, the UART will go into a 'locked' error state. Since you have nothing to handle this error, the UART will remain locked for ever (ERRORS adds code to clear this).

However then think. This implies characters have been missed. These are lost for ever....

Look in the code library, there is a complete GPS parser there.
dream10101tysh



Joined: 17 Apr 2013
Posts: 3

View user's profile Send private message

PostPosted: Sat Sep 06, 2014 4:52 pm     Reply with quote

Thanks to all, I try to correct the code with circular buffer, while I don't know why the PIC only display "MDD",and nothing more. Here is my guess:

The "buffer" is filled fully and can not be put into "gpsMTK[len]" respectively. Maybe the RDA_isr() is too frequently that the while loop is not able to complete. But in that case the RDA_buf is always in "1", therefore, RDA_isr() service time is short. I must be able to complete my while-loop and make the RDA_buf=0 at least one time? Why not?

Since I want to retain my main algorithm to solve GPS data, then I use " buffer[BUFFER_SIZE],gpsMTK[BUFFER_SIZE]" in the code. BUFFER_SIZE is 128. Is that the problem? Loading is too heavy?

THANK YOU


Code:
#INT_RDA
void RDA_isr(void)
{
  if(RDA_buf == 0)
  {
    int8 t;
   
    buffer[next_in] = getc();
   
    if(++next_in == BUFFER_SIZE) 
    {
      next_in = 0;
      RDA_buf = 1;
    }
   
  }
}


int8 bgetc(void)
{
  int8 c;
 
  c = buffer[next_out];
  next_out = (next_out+1) % BUFFER_SIZE;
  printf("%c",'D');
  return(c);
}


void main()

  for(n=0 ; n<BUFFER_SIZE ; n++) 
  {
    buffer[n]=0;
    gpsMTK[n]=0;
  }
 
  enable_interrupts(INT_RDA);
  enable_interrupts(GLOBAL);
       
  while(TRUE)
  {
    if(RDA_buf == 1)
    { printf("%c",'M');
 for(len =0 ; len < BUFFER_SIZE ; len++)  gpsMTK[len] = bgetc();
     
      for(gMTK_i = 0 ; gMTK_i < BUFFER_SIZE ; gMTK_i++)
      {
        tmp_MTK[0] = tmp_MTK[1];
        tmp_MTK[1] = tmp_MTK[2];
        tmp_MTK[2] = gpsMTK[gMTK_i];
....} RDA_buf = 0;
Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Sun Sep 07, 2014 12:24 am     Reply with quote

One simple thing.

The RDA interrupt _must_ always read the character. Otherwise it'll never exit.
Code:

#INT_RDA
void RDA_isr(void)
{
  int8 temp;
  temp=getc();
  if(RDA_buf == 0)
  {
    buffer[next_in] = temp; 
    if(++next_in == BUFFER_SIZE)
    {
      next_in = 0;
      RDA_buf = 1;
    }
  }
}


Note that the actual 'read' always occurs. It _has to_. The RDA interrupt says 'there is a character waiting to be read'. If you exit, without reading this, the interrupt will trigger again immediately, since there is still a 'character waiting to be read'.
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Sun Sep 07, 2014 2:21 pm     Reply with quote

Hi,

You've also modified the example program to get rid of the 'bkbhit' functionality, and thus you are calling 'bgetc' regardless of whether a new character has been placed in the buffer or not.....

'Ex_sisr.c' works, so I recommend not straying too far from it!

John
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