usart_receive() for 5 seconds ?

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Guys,

How can I make usart_receive() for only 5 seconds and if there's no command, continue with other task ?

Any clues ?

thanks
Code:

 

lcd_cmd(0x01);
  lcd_string("WAIT FOR COMMAND!");
  option=usart_receive();
  if (option=='1')
  {
	  tone(100);
	  _delay_ms(100);
	  tone(0);
	  lcd_cmd(0x01);
	  lcd_string("Bluetooth CMD!");
	  _delay_ms(1000);
  }
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bianchi77 wrote:
How can I make usart_receive() for only 5 seconds and if there's no command, continue with other task ?

Why you want to stall other tasks at all ?

The typical approach was, to do other tasks until a complete command was received:

  for(;;){
    if( byte_received() ){
      put_byte_into_buffer();
      if( command_completed() ){
        parse();
        execute();
      }
    }
    do_other_tasks();
  }

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you really mean that you want uart_receive() to come back after 5 seconds if nothing is actually received?

Assuming it's a synchronous/blocking function it presumably blocks waiting for the RXC bit to be set with something like:

char uart_receive(void) {
  while (!(UCSRA & (1 << RXC)));
  return UDR;
}

(simplistically)

So what you really want is something like:

char uart_receive(void) {
  while ((!(UCSRA & (1 << RXC))) && five_seconds_haven't_passed);
  return UDR;
}

Now how you arrange to make that five_seconds_havn't_passed is another question.

One way is if you already run a timer interrupt, say it ticks every 10ms then there are 500 lots of 10ms in five seconds so you could do something like:

char uart_receive(void) {
  time_count = 500;
  while ((!(UCSRA & (1 << RXC))) && time_count);
  return UDR;
}

then in the timer ISR you have:

ISR(TIMER_vect) {
 if (time_count) time_count--;
}

(obviously the variable has to be volatile).

So every 10ms while time_count is non-0 it is decremented and when it reaches 0 the while() loop in uart_receive() is released (but it shouldn't read/return UDR in this case but needs to flag to the caller that it just timed out).

Another strategy without interrupts is to break the waiting time into small chunks:

char uart_receive(void) {
  uint8_t time_count = 500;
  while (1) {
   if (UCSRA & (1 << RXC))) break;
   if (time_count-- == 0) break;
   _delay_ms(10);
  }
  return UDR;
}

That will look at UCSRA every 10ms and if either RXC gets set or the time_count counts reaches 0 it will stop waiting.

Again don't just return UDR if it timed out, return something to say that uart_receive() did not succeed. A common way to do this is rather than return char/uint8_t return an int16. Set it to UDR if no timeout or -1 if it does time out. The code that calls uart_receive() can then check the return to see if it is -1 and possibly do something different if there has been a timeout.