|
|
View previous topic :: View next topic |
Author |
Message |
jj3316 Guest
|
Using fgets() without freezing program? |
Posted: Sun Oct 28, 2007 9:34 pm |
|
|
I am trying to read in bitstreams that might look something like...
(Data)(carriage return)(Next piece of data)(Carriage return)(More data)(Carriage return)
Therefore reading this would require 3 fgets() since there's 3 carriage returns. However, the number of blocks of data I have may vary (it's 3 here, but could be 4, 6, whatever) but I can't just use fgets() to keep checking on data since it'll freeze the program if nothing's coming. Does anybody know of a good way to implement fgets() only when needed? I tried using some code with kbhit() but it didn't work (perhaps due to something i read about the hardware buffer only being able to store 3 characters?).
Any suggestions would be greatly appreciated.
Thanks! |
|
|
Ttelmah Guest
|
|
Posted: Mon Oct 29, 2007 5:11 am |
|
|
Multiple ways.
First, look at the code for 'get_string', in input.h.
You can use this with a timed getc, to get a string or return if the data is not available in a time period.
However I'd possibly consider approaching it slightly differently. Look at the example EX_SISR.C, which shows how to implement a software interrupt driven receive buffer. Then modify this in one way. Add a single 'flag' bit, to say that the end of a string has been seen (/r or /n). Set this in the interrupt when the character is seen.
Then in your main, simply test this bit. If it is not set, a complete 'string' has not been received. Carry on with other tasks till it is set. Then as soon as you see it, clear it, and call a modiied version of input.c,but taking the characters from the software buffer. At any time, if this is set, you 'know' that a complete string is available in the buffer.
Best Wishes |
|
|
g159 Guest
|
|
Posted: Thu Nov 01, 2007 9:51 pm |
|
|
Hey Ttelmah,
Thanks for the insight. I am trying your suggestion of using some kind of timed routine for fgets() so that it stops trying to receive a string after a certain time out. After searching through this forum, I thought I might try a timer-interrupt based method of doing so, and I came up with the following code:
Code: |
#int_timer0
void timer0isr(){
fprintf(SW, "Interrupted\r\n");
}
void main () {
delay_ms(1000);
while (TRUE)
{
/* ASCII Equivalent of get inventory command */
fprintf(HW, "\r000201018200\r");
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256|RTCC_8_BIT);
set_timer0(0);
enable_interrupts(global);
enable_interrupts(INT_TIMER0);
// Wait for information to come in
fgets(response, HW);
disable_interrupts(INT_TIMER0);
}
}
|
I am using a 20 MHz clock, so the system clock is 5 MHz, period is 0.2 us, and thus there should be a overflow every 0.0131 secs right? When this program runs, it seems to just display "Interrupted" endlessly, and my ASCII command inside main() is never sent out after the initial first time.
Overall, I guess I am just very confused on how the structure of using a timed interrupt towards this should work. Ideally, I want my program to do the main() function, then timeout after a certain period, run the interrupting function, and then return back to the beginning of main() to send the ASCII command over.
Is there something obviously wrong with my code? I am very new to this so that's likely the case...
Thanks a lot--- Any help would be greatly appreciated. |
|
|
Ttelmah Guest
|
|
Posted: Fri Nov 02, 2007 4:06 am |
|
|
What you post, has no relationship to a time limited getc!....
Interrupts, return to exactly where they occur. They don't take you 'out' of the code, so fgets will still be hung, just with an 'interrupted' message added....
Though I don't like doing the work:
[code]
int1 timeout=false;
int8 waitfor;
char response[20]; //however long is needed...
#define second (77)
#define timed_source HW
#int_timer0
void timer0isr(){
//Count down if the 'waitfor' is not zero
if (waitfor) --waitfor;
else timeout=true;
}
void ftget_string(char* s, int max, int ticks) {
//Modified version of the get_string function, to timeout
//in 'ticks' count of the timer interrupt
//no echo, or backspace handling.
int len;
char c;
waitfor=ticks;
timeout=false;
//start the timeout tick
set_timer0(0);
clear_interrupt(int_timer0)
enable_interrupts(INT_TIMER0);
--max;
len=0;
do {
//If no key is available, check for the timeout
while (!kbhit(timed_source)) {
//If timeout occurs, terminate the string
if (timeout) {
c=13;
break;
}
}
if (kbhit(timed_source)) c=fgetc(timed_source);
if ((c>=' ')&&(c<='~'))
if(len<=max) {
s[len++]=c;
// restore this if echo required putc(c);
}
} while(c!=13);
s[len]=0;
//Disable interrupt when not wanted
disable_interrupts(INT_TIMER0);
}
void main () {
delay_ms(1000);
//Setup timer, and enable the global interrupt flag once
enable_interrupts(GLOBAL);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256|RTCC_8_BIT);
while (TRUE) {
/* ASCII Equivalent of get inventory command */
fprintf(HW, "\r000201018200\r");
// Wait for information to come in max 20 chars, and 1 second
ftget_strings(response, 20, second);
//Do something here to look at what you have got...
}
}
Best Wishes |
|
|
g159 Guest
|
|
Posted: Mon Nov 05, 2007 2:38 pm |
|
|
Hey Ttelmah,
I really appreciate the help. I went through your code and I want to make sure I understand it correctly:
So basically, the interrupt timer has been set up with parameters such that 77 ticks corresponds to 1 second of time. When ftget_string is called, the timer starts counting down in the background regardless of whether there is a character to read in or not. Once a character is available, it gets read in, and the timer is stopped (to be reset with the next iteration of ftget_string). If a character is not available at the point which the timer has overflowed, then a carriage return is put in place and getc() is never called.
Is there anything important I am missing?
Thanks again. You are awesome. |
|
|
Ttelmah Guest
|
|
Posted: Mon Nov 05, 2007 4:13 pm |
|
|
As written, I don't stop the timer, when characters are received (this is an alternative approach, all you do, is when a character is 'seen', reset the counter to the 'timeout' value - you can then use a lower value, so the code will return if - for instance - no character is seen in 1/10th second). Instead I allow one second for the whole string to arrive. If it doesn't, what has arrived so far is returned, and the routine returns.
Depending on the 'nature' of your needs, you would have to choose which approach suits you.
Best Wishes |
|
|
sri...... Guest
|
hanging |
Posted: Wed Jul 08, 2009 4:22 am |
|
|
I am using your code. It works better when no other timers are used but when timer1 and timer2 are used along with the code, it receives only two characters instead of whole string or some times it receives junk.
Please help me...Ttelmah |
|
|
Ttelmah Guest
|
|
Posted: Wed Jul 08, 2009 4:31 am |
|
|
It sounds as if you are spending longer than a character 'time', in the handlers for your other interrupts.
First add 'ERRORS' to your #use RS232 declaration. You will still lose individual characters, but it should then recover.
Then study the code you are using in your interrupts, and shorten it. Basic 'mantra', "keep interrupt handlers fast". Unless you do this, you _will_ cause problems.
Best Wishes |
|
|
|
|
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
|