Retardo de tiempo AVR sin bibliotecas Arduino

Tratando de descubrir cómo hacer algo como retrasar () en Arduino pero solo para el código AVR directo. ¿Cuál es la forma típica de hacer esperas y cosas así en los chips AVR?

El uso de un temporizador es la forma habitual. Eso es probablemente lo que hace el Arduino.
avr_libc proporciona _delay_ms y _delay_us nongnu.org/avr-libc/user-manual/group__util__delay.html

Respuestas (1)

Usted tiene un par de opciones:

1) Usar una interrupción. La configuración es un poco complicada pero libera su dispositivo para hacer otras cosas mientras espera. Consulte la hoja de datos de su AVR para obtener instrucciones sobre cómo configurar una interrupción. Para retrasos mayores que el contador de interrupciones, puede usar un escalador previo u otra variable para contar las interrupciones hasta que se produzca la espera deseada.

2) Use un NOP en un bucle for para realizar su espera. De acuerdo con esta página - http://playground.arduino.cc/Main/AVR , una operación NOP toma 1 ciclo de reloj - 1 ciclo de reloj = 1/frecuencia. A 16 MHz, un NOP tardará 62,5 nS en ejecutarse. use una variable larga sin signo cuando defina su contador de bucle para que no se dé la vuelta.

Su contador de bucle se verá así (volátil asegura que la compilación no optimizará el código):

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

Editar: habrá algunos gastos generales del bucle for. Puedes determinar esto experimentalmente (fácil) o contando las instrucciones (difícil).

¿No es para eso util/delay(cf. el comentario de Gorloth ?)
Sí. También puede usar util/delay. Las interrupciones son el método preferido ya que ahorra energía a través de una frecuencia requerida más baja y una mayor utilización del dispositivo. Codificar su retraso a mano también permite una mejor optimización.
Perdón por no ser claro... Supongo que me pregunto por qué escribirías tu función de retardo en lugar de usar las de la biblioteca. ¿ No es como escribir el tuyo propio strtok()o malloc()? ¿ Quieres optimizar un bucle de espera? Creo que si se prefieren o no las interrupciones realmente depende de su aplicación. Muchas veces se necesita una espera de bloqueo, ¿no?
La optimización aquí no se refiere a la velocidad sino a hacer que el código se adapte a sus necesidades. Por ejemplo, la función util/delay delay_us() establece que el retraso máximo es 768 us/F_CPU en MHz. ¿Qué pasa si quieres retrasar más que eso? Se puede hacer un argumento similar para la función delay_ms() . Solo por curiosidad, ¿dónde usarías una espera de bloqueo? Es mejor poner su dispositivo a dormir con una interrupción de activación y ahorrar energía.
Lo usaría donde la energía no es un problema, donde el costo de dormir y despertar es demasiado alto, cuando todos sus temporizadores/interrupciones hacen otra cosa. Al hacer bitbanging, por ejemplo, el bloqueo de esperas es muy útil.