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

gets() does not work proper in interrupt!!!

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



Joined: 14 Jul 2007
Posts: 38

View user's profile Send private message

gets() does not work proper in interrupt!!!
PostPosted: Wed Jul 14, 2010 1:07 am     Reply with quote

hi everbody,
i am trying to make communicate a 18f452 and PC(visual basic).
at PC side,(by using command button)
mscomm1.output = set+","set2+","+set3+","+";"+chr(13)


at pic side to receive and seperate data(which were seperated by commas)

gets(string); // string[10]
strcpy(term,",;");
ptr = strtok(string, term);
while(ptr!=0) {
receive_buffer(ptr); // *ptr , receive buffer[10]
ptr = strtok(0, term);
i++; // i int8
}


my problem is that:

the above code is working well in main(). however, i would like to get the serial data in interrupt routine. in this case the code works only once or twice.!!!

i did not know how to deal with it.

thanks in advance...
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Wed Jul 14, 2010 1:24 am     Reply with quote

gets() is waiting for data until the terminating character, it's absolutely unsuitable for interrupt usage.

A reasonable way to achieve what you intend is to write the received serial data to a buffer during interrupt and process the buffer in the main() loop. A ring buffer involving two pointers is the most versatile way. There are geenric examples for buffered UART receive shipped with CCS C, I hope. At least, buffered UART is used with the MODBUS examples. Personally, I use to write it from the scratch, so I don't care much for the examples.
ferkar



Joined: 14 Jul 2007
Posts: 38

View user's profile Send private message

PostPosted: Wed Jul 14, 2010 1:44 am     Reply with quote

strtok() command seperate the data

and chr(13) is terminating character.

therefore it should work i think...
Ttelmah



Joined: 11 Mar 2010
Posts: 19387

View user's profile Send private message

PostPosted: Wed Jul 14, 2010 3:58 am     Reply with quote

You need to understand a basic point.
The serial interrupt means that _just one_ character is waiting.
gets, waits for an entire string to arrive.
If you call gets, in an interrupt, the code _will_ be hung inside the interrupt, till the whole string arrives.
This has been covered many hundreds of times here in the forum.

ex_sisr.c, shows how to use serial interrupts to store characters into a buffer.
As a sort of 'semi example', I'm posting a set of code (untested - as typed), to put characters into a buffer like ex_sisr, but add the following features:
1) Handle the buffer maths efficiently, if buffer size is not a binary multiple - a fault in ex_sisr.
2) Offer a 'bgetline' function to get a complete CR terminated line from the buffer.
3) Offer a 'line_waiting' test, to say that a CR terminated line has been received.

There are 'caveats' with it, but with care, it should provide a starting point.
Code:

////For whatever chip you want....
#include <16f877A.h>
#fuses HS, NOLVP, NOWDT, PUT
#use delay (clock = 20000000)
#use rs232(baud=9600, Bits=8, Parity=N, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
////

//Buffer definitions
#define CR (13)
int8 CR_seen=0;
int1 Overflow=FALSE; //Logic flags for serial handling

#define BUFFER_SIZE 32 //Change this to alter the buffer size
char buffer[BUFFER_SIZE];
int next_in = 0; //Max 255 chars with int here - change if larger needed
int next_out = 0;

#int_rda
void serial_isr(void) {
   int temp;
   temp=getc();
   buffer[next_in]=temp;
   if (temp==CR) CR_seen++; //flag if a carriage return
   temp=next_in;
   if (++next_in==(BUFFER_SIZE)) next_in=0;
   
   if(next_in==next_out) {
     next_in=temp;  //Buffer overflow
     Overflow=TRUE;
   }
}

#define bkbhit() (next_in!=next_out) //True is character waiting to be read
#define line_waiting() (CR_seen) //True if _line_ waiting to be read

char bgetc() { //Get single char from buffer - wait if one not ready
   char c;
   while(!bkbhit()) ;
   c=buffer[next_out++];
   if (next_out==BUFFER_SIZE) next_out=0;
   if ((c==CR)&&(CR_seen>0)) CR_seen--; //If I read a carriage return from buffer
   return(c);
}

int1 bgetline(char * str, int MAX) { //Routine to get a line from buffer - returns false if no line...
//MAX is the maximum number of characters to return
   int8 ctr;
   int8 temp;
   MAX--; //make space for null terminator
   if (!line_waiting()) {
      *str=0; //terminate null string
      return 0;
   }
   for (ctr=0;ctr<MAX;ctr++) {
     if ((temp=bgetc())==CR) { //This will give a compiler warning, but is correct.....
        *str=0;
        return ctr; //Null terminate and exit
     }
     *(str++)=temp;
   }
   if (buffer[next_out] == CR) bgetc(); //dump a character if next is CR
   *str=0;
   return ctr;
} //Returns the number of characters in the 'line'

void main (void) {

   int16 dummy;
   char line[20];
   char chr;
   
   while (TRUE) { //sit looping doing something.....
      delay_ms(100);
      dummy++;
      printf("%ld/n/r",dummy);
      //Only use _one_ of the following at a time.
     
      //Now you can test if a character is waiting, and get it like:
      if (bkbhit()) chr=bgetc();
     
      //Or wait for a line with:
      if (line_waiting()) {
         bgetline(line,20);
         //here have a line to process
      }
     
      //or get a line with:
      if (bgetline(line,20)) {
         //Here I have a line to process - since bgetline only returns 'true'
         //if a line was retrieved.
         
      }
      //Now, _caveats_. The code keeps a count of carriage return characters read
      //if the buffer overflows, data _will_ be thrown away. If this happens the
      //count may become wrong - need to ensure, that either the buffer _is_ big
      //enough, or this is handled, by checking the 'overflow' flag....
      //Second, the bgetline will return with a line, if the count of characters
      //exceeds 'MAX', even if this is not a complete 'line' from the code.
      //You need to ensure that the length of the storage is greater than the
      //maximum line length you expect (+1), otherwise line parsing will
      //become hard.....   
   }
}


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