View previous topic :: View next topic |
Author |
Message |
edhaslam
Joined: 15 Jul 2005 Posts: 89 Location: UK
|
do while timeout? |
Posted: Fri Oct 07, 2005 5:47 am |
|
|
Hi All,
I'm trying to implement a timeout for a do while loop that could potentially loop for ever if a character isn't received.
I've tried the following but it doesn't seem to work:
Code: |
long timeout;
timeout=0;
do
{
ch=getch();
delay_us(10);
timeout++;
}
while (ch != 'B'||(timeout>100000));
|
This should time out after a second, but just loops forever. Is what i'm doing correct or is there a better way to do this?
Ed |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Fri Oct 07, 2005 5:58 am |
|
|
A long is 16bits
100000 would require a 32bit number
declare it as int32 instead |
|
|
Ttelmah Guest
|
|
Posted: Fri Oct 07, 2005 6:19 am |
|
|
There is also another caveat. As written, if no character arrives, it'll sit waiting in the 'getch', and never increment the 'timeout'. Use:
Code: |
long timeout;
timeout=0;
ch=0;
do {
if (kbhit()) ch=getch();
//Remember that the loop itself will include several
//instructions, so depending on processor speed, the
//'loop time', will probably be more like 20uSec
delay_us(10);
} while (ch != 'B' && (timeout++<50000));
|
To give 'exit after time', even if no charactrs arrive.
Best Wishes |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Fri Oct 07, 2005 6:22 am |
|
|
Code: |
do
{
ch=getch();
delay_us(10);
timeout++;
}while (ch != 'B'||(timeout>100000));
|
getch() seat and wait until a char is received,
so timeout would never increment.
To get a running loop, timeout should be incremented inside a timer interrupt
handler (in background) or modifying your code adding kbhit()
Code: |
long timeout;
timeout=10000; // 10K !!!
do
{
if(kbhit())
{ch=getch();}
else
{delay_us(100); // 100us !!!
timeout--; }
}while (ch != 'B' && (timeout));
|
Humberto
Edited by Humberto
Hi Ttelmah, we are responding in a shared way at same time!!!
Last edited by Humberto on Fri Oct 07, 2005 6:38 am; edited 3 times in total |
|
|
edhaslam
Joined: 15 Jul 2005 Posts: 89 Location: UK
|
|
Posted: Fri Oct 07, 2005 6:22 am |
|
|
Mark wrote: | A long is 16bits
100000 would require a 32bit number
declare it as int32 instead |
Ah, yes. Silly mistake!
I've just re compiled but it still doesn't seem to jump out of the do-while loop. It must be getting stuck somewhere else in my code. Here's what I have so far. It is a comms function that send 32 blocks of 128 byte data over the serial port. Before the first block and subsequent blocks are sent, the hardware must receive a 'B' character from the PC in order to proceed:
Code: |
void TxData(void)
{
#define DATA_BLOCK_SIZE 125
#define DATA_BLOCK_NUM 31
char ch;
int data, B;
long block_inc=0, x=0, mem_pointer=0, i;
int32 timeout;
delay_ms(100);
putc(0x52); // Send 'R' char for 'Ready'
disable_interrupts (GLOBAL); // Turn off during async Tx
lcd_gotoxy(2,1);
printf(lcd_putc,"\f\ Downloading Data!"); // Send start message
lcd_gotoxy(2,2);
printf(lcd_putc,"Tx at 9600-8-N-1"); // Display data Tx rate
delay_ms(1500);
for (i=0; i<DATA_BLOCK_NUM; i++) // 32 blocks of data to Tx
{
timeout=0;
do
{
ch=getch();
delay_us(10);
timeout++;
}
while (ch != 'B'||(timeout>100000));
for (x=0; x<DATA_BLOCK_SIZE; x++) // 128 bytes of data tx
{
data = read_ext_eeprom (DATA_BLOCK_SIZE +
mem_pointer * 256)); mem_pointer++;
if ( data == 0x101 ) // Quick check on data integrity
{
printf(lcd_putc, "%u Out of Range\r\n", data); // Out-of-range
delay_ms(3000);
}
else
{
printf ("%03u", data); // Send data sample
}
delay_ms (0.4);
}
}
delay_ms(1000);
lcd_gotoxy(3,1); // Print message at pos 1, line 1
printf(lcd_putc,"\f\ Download Complete!"); // Send 'done' message to display
delay_ms(2000);
enable_interrupts (GLOBAL); //Turn interrupt on again
}
|
Any comments welcome!
Ed |
|
|
edhaslam
Joined: 15 Jul 2005 Posts: 89 Location: UK
|
|
Posted: Fri Oct 07, 2005 6:26 am |
|
|
You beat me to it! Many thanks guys, I can see what I'm doing now. I'll let you know how I get on.
Cheers,
Ed |
|
|
Ttelmah Guest
|
|
Posted: Fri Oct 07, 2005 7:03 am |
|
|
Hi Humberto,
It is amazing how often that happens. You post an answer, and sombody else has already posted an almost identical comment. There was a thread here a while ago, with about five answers all posted 'overlapping' like this!.
Best Wishes |
|
|
edhaslam
Joined: 15 Jul 2005 Posts: 89 Location: UK
|
|
Posted: Fri Oct 07, 2005 7:24 am |
|
|
Ttelmah wrote: | Hi Humberto,
It is amazing how often that happens. You post an answer, and sombody else has already posted an almost identical comment. There was a thread here a while ago, with about five answers all posted 'overlapping' like this!.
Best Wishes |
You both must have posted about a second before I did!
Ok, I've got the loop working now
BUT, I still have a problem. The function txdata.c, shown below, doesn't return to the main program if I re enable the global interrupts:
Code: |
void TxData(void)
{
#define DATA_BLOCK_SIZE 125 // Size of block to transmit
#define DATA_BLOCK_NUM 31 // Number of blocks to tx
char ch;
int data, B;
long block_inc=0, x=0, mem_pointer=0, i;
int32 timeout;
putc(0x52); // Send 'R' char for 'Ready'
disable_interrupts (GLOBAL); // Turn off during async Tx
lcd_gotoxy(2,1);
printf(lcd_putc,"\f\ Downloading Data!");
lcd_gotoxy(2,2);
printf(lcd_putc,"Tx at 9600-8-N-1"); // Display data Tx rate
delay_ms(1500);
for (i=0; i<DATA_BLOCK_NUM; i++) // 32 blocks of data to Tx
{
timeout=0;
ch=0;
do
{
if (kbhit()) // Time out to prevent infinite loop
ch=getch(); // Several instructions so
// 'loop time' will probably be more like 20uSec
delay_us(10);
}
while (ch != 'B' && (timeout++<30000));
for (x=0; x<DATA_BLOCK_SIZE; x++) // 128 bytes of data to Tx
{
data = read_ext_eeprom (DATA_BLOCK_SIZE + (mem_pointer * 256)); // Get sample data: 8-bit
mem_pointer++; // Keeps track of next memory 'block'
if ( data == 0x101 ) // Quick check on data integrity
{
printf(lcd_putc, "%u Out of Range\r\n", data); // Out-of-range
delay_ms(3000);
}
else
{
printf ("%03u", data); // Send data sample
}
delay_ms (0.4);
}
}
enable_interrupts (GLOBAL); //Turn global interrupt on again
lcd_gotoxy(3,1); // Print message at pos 1, line 1
printf(lcd_putc,"\f\ Download Complete!"); // Send 'done' message
}
|
So if don't dissable/enable the interrup in this function, everything works fine. If I do, the program halts at the 'printf(lcd_putc,"\f\ Download Complete!");' .
Is there any reason why this might happen?
Cheeers, |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Fri Oct 07, 2005 7:39 am |
|
|
A couple of comments
isn't really valid. You need to use whole numbers.
What happens if you don't get a 'B', you still keep on sending and waiting for subsequent B's. You ought to have a failure mode. |
|
|
edhaslam
Joined: 15 Jul 2005 Posts: 89 Location: UK
|
|
Posted: Fri Oct 07, 2005 8:12 am |
|
|
Mark wrote: | A couple of comments
isn't really valid. You need to use whole numbers. |
Good point
Quote: |
What happens if you don't get a 'B', you still keep on sending and waiting for subsequent B's. You ought to have a failure mode. |
Yes, the amount of Bs sent by the PC to the hardware governs the amount of blocks of data that the hardware sends to the PC. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Fri Oct 07, 2005 8:29 am |
|
|
edhaslam wrote: | Mark wrote: | A couple of comments
isn't really valid. You need to use whole numbers. |
Good point
Quote: |
What happens if you don't get a 'B', you still keep on sending and waiting for subsequent B's. You ought to have a failure mode. |
Yes, the amount of Bs sent by the PC to the hardware governs the amount of blocks of data that the hardware sends to the PC. |
My point is that is you timeout once, then the PC is probably not sending the B's anymore but you still keep trying. I think you should bail out or your program will appear to hang for a very long time. |
|
|
arunb
Joined: 08 Sep 2003 Posts: 492 Location: India
|
RE: |
Posted: Fri Oct 07, 2005 8:32 am |
|
|
Hi,
Just use the RS 232 receive interrupt. That way all you have to do is enable the interrupt and then sit in an inifinite Do...While loop.
thanks
arunb |
|
|
edhaslam
Joined: 15 Jul 2005 Posts: 89 Location: UK
|
|
Posted: Fri Oct 07, 2005 8:40 am |
|
|
Quote: |
My point is that is you timeout once, then the PC is probably not sending the B's anymore but you still keep trying. I think you should bail out or your program will appear to hang for a very long time. |
Yes, I see what you mean. But the program does exit in practice, but as soon as I add in the enable/disable global interupts it hangs. Is it because of how the whole loop has been designed? Can you suggest a better way of doing this part of the code?
The structure is: the PC sends a 'G' character to the hardware which trips the RDA interrupt. This calls txdata() which sends an 'R' character to tell the PC it is ready to send the data. The PC then sends a B character for every block it needs to receive.
Ed
Last edited by edhaslam on Fri Oct 07, 2005 8:53 am; edited 1 time in total |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Fri Oct 07, 2005 8:48 am |
|
|
Test for the B after the while loop. You can set a flag and break from the for loop or you could make the txdata return a value and just do a return(false) if you don't get a B. If you set a flag, and the bottom, you test for the flag and display a failed message. Of course you could do this inside the check for B inside the for loop. |
|
|
edhaslam
Joined: 15 Jul 2005 Posts: 89 Location: UK
|
|
Posted: Fri Oct 07, 2005 8:58 am |
|
|
Mark wrote: | Test for the B after the while loop. You can set a flag and break from the for loop or you could make the txdata return a value and just do a return(false) if you don't get a B. If you set a flag, and the bottom, you test for the flag and display a failed message. Of course you could do this inside the check for B inside the for loop. |
The strange thing is that it does seem to work if I don't dissable and enable the global interrupts?! |
|
|
|