2
\$\begingroup\$

Trying to figure out how to do something like delay() in Arduino but just for straight AVR code. What's the typical way to do waits and such on AVR chips?

\$\endgroup\$
2
6
\$\begingroup\$

You have a couple options:

1) Use an interrupt. The setup is slightly complicated but frees up your device to do other things while it is waiting. Refer to your AVR datasheet for instructions on how to set an interrupt. For delays greater than the interrupt counter, you can use a pre-scaler or another variable to count interrupts until your desired wait has occurred.

2) Use a NOP in a for loop to perform your wait. According to this page - http://playground.arduino.cc/Main/AVR, a NOP operation takes 1 clock cycle - 1 clock cycle = 1/frequency. At 16MHz a NOP will take 62.5nS to execute. use an unsigned long variable when defining your loop counter so you don't roll over.

Your loop counter will look like this (volatile ensures that the compile will not optimize out the code):

void delay(unsigned long delay) {
  volatile unsigned long i = 0;
  for (i = 0; i < delay; i++) {
      __asm__ __volatile__ ("nop");
  }
}

Edit: There will be some overhead from the for loop. You can determine this experimentally (easy) or by counting the instructions (hard).

\$\endgroup\$
5
  • \$\begingroup\$ Isn't that what util/delay for (cf. Gorloth's comment?) \$\endgroup\$ Apr 4 '13 at 23:40
  • \$\begingroup\$ Yes. You can also use util/delay. Interrupts are the preferred method since that saves power via lowered required frequency and greater device utilization. Coding your delay by hand also allows for better optimization. \$\endgroup\$
    – xyzio
    Apr 4 '13 at 23:48
  • \$\begingroup\$ Sorry for not being clear... I guess I am wondering why would you write your down delay function instead of using the library ones? Isn't that like writing your own strtok() or malloc()? You want to optimize a waitloop? I think whether interrupts are preferred or not really depends on your application. Many times do need a blocking wait, no? \$\endgroup\$ Apr 4 '13 at 23:51
  • \$\begingroup\$ Optimization here doesn't refer to speed but rather to make the code suit your needs. For example, the util/delay delay_us() function states that the maximum delay is 768 us / F_CPU in MHz. What if you want to delay longer than that? A similar argument can be made for the delay_ms() function. Just curious, where would you use a blocking wait? It is better to put your device to sleep with a wake-up interrupt and save power. \$\endgroup\$
    – xyzio
    Apr 5 '13 at 3:50
  • \$\begingroup\$ You'd use it where power isn't an issue, where the cost of sleeping and wakeup is too great, when all your timers/interrupts do something else. When bitbanging, for instance, blocking waits are very useful. \$\endgroup\$ Apr 5 '13 at 3:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.