Ttelmah
Joined: 11 Mar 2010 Posts: 19811
|
|
Posted: Wed Dec 18, 2013 1:43 am |
|
|
Key to understand is that there is no magic about functions. gets, is not a terribly 'good' function to use, since it effectively hangs the chip sitting waiting for a whole string to arrive. It is designed really for it's original use, where the program was talking to a 'terminal', sitting waiting for somebody to type replies, not for programs that are actually meant to be doing anything constructive while waiting. Even worse, if a line feed is missed/missing, it'll result in memory being corrupted as it carries on storing characters into space that isn't available for it. Now, there is a replacement for gets, 'get_string', in the include file 'input.c', which shows a fractionally improved way of doing this, with a maximum string length implemented.
It is also not a complex function to write (as you will see if you look at 'get_string'. What you should do, is use ex_sisr, and add one test in the interrupt that sets a flag, when a line feed is seen. So:
Code: |
#define BUFFER_SIZE 32
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
int1 have_line=FALSE;
#int_rda
void serial_isr(void)
{
int t, c;
c=getc();
buffer[next_in]=c;
if (c==13)
have_line=TRUE; //we have a line feed
t=next_in;
if (++next_in==BUFFER_SIZE)
next_in=0;
if(next_in==next_out)
next_in=t; // Buffer full !!
}
|
Now this has lots of little changes. The '%' operator as a way of limiting the buffer size, works well, if the buffer size is a binary multiple (2,4,8,16,32 etc.), but becomes foul if a non binary size is used. Hence the change to the test instead of using this. Means you can use odd buffer sizes like 50 characters if required.
Then array accesses with a variable are quite inefficient, and since I need to both test the character, and write it to the array, it uses a temporary variable so the array only has to be accessed once.
Then you can have a your_getstring function as :
Code: |
int1 your_getstring(char* s, unsigned int8 max)
{
unsigned int8 len;
char c;
if (have_line==FALSE)
return FALSE; //return if no line available
max-=2;
len=0;
do
{
c=bgetc();
if(len<max)
{
s[len++]=c;
}
}
while(c!=13);
s[len]=0;
return TRUE;
}
|
This does no processing at all. It just loads the string into the array you specify, up to a maximum of 'max' characters (less one to allow for the NULL terminator that is added). Doesn't echo like the supplied get_string.
But key difference is that it returns TRUE/FALSE according to whether a string is available.
So:
Code: |
char my_string[20];
while (TRUE)
{
if (your_get_string(my_string,sizeof(my_string)))
{
//Now you have a string in 'my_string' - process it
}
//You will though keep looping, and can do other jobs if a string
//hasn't arrived......
}
|
The basic thing is you _only_ actually go and pull the line from the buffer, when a complete line _has_ been received.
Hope you can make sense of this - no guarantees I haven't left a few syntax errors hiding....
Best Wishes |
|