Mahdi
Mahdi

Reputation: 21

How to make delay microsecond in AVR (ATmega8) with timer?

I want to make variable delay in ATmega8. But in function delay_us(), I can just put a constant value. I think I can make a variable delay microsecond with a timer but I don't know how to work with this.

Please help me.

Upvotes: 2

Views: 3713

Answers (1)

Edgar Bonet
Edgar Bonet

Reputation: 3566

You can use a delay loop: you delay for one microsecond in each iteration, and do as many iterations as microseconds you have to burn:

void delay_us(unsigned long us)
{
    while (us--) _delay_us(1);
}

There are, however, a few issues with this approach:

  • it takes time to manage the iterations (decrement the counter, compare to zero, conditional branch...), so the delay within the loop should be significantly shorter that 1 µs
  • it takes time to call the function and return from it, and this should be discounted from the iteration count, but since this time may not be a full number of microseconds, you will have to add a small delay in order to get to the next full microsecond
  • if the compiler inlines the function, everything will be off.

Trying to fix those issues yields something like this:

// Only valid with a 16 MHz clock.
void __attribute__((noinline)) delay_us(unsigned long us)
{
    if (us < 2) return;
    us -= 2;
    _delay_us(0.4375);
    while (us--) _delay_us(0.3125);
}

For a more complete version that can handle various clock frequencies, see the delayMicroseconds() function from the Arduino AVR core. Notice that the function is only accurate for a few discrete frequencies. Notice also that the delay loop is done in inline assembly, in order to be independent of compiler optimizations.

Upvotes: 2

Related Questions