AVR-Zeitverzögerung ohne Arduino-Bibliotheken

Ich versuche herauszufinden, wie man so etwas wie delay () in Arduino macht, aber nur für direkten AVR-Code. Was ist der typische Weg, um Wartezeiten und dergleichen auf AVR-Chips durchzuführen?

Die Verwendung eines Timers ist der übliche Weg. Das ist wahrscheinlich das, was der Arduino tut.
avr_libc stellt _delay_ms und _delay_us bereit nongnu.org/avr-libc/user-manual/group__util__delay.html

Antworten (1)

Sie haben ein paar Möglichkeiten:

1) Verwenden Sie einen Interrupt. Die Einrichtung ist etwas kompliziert, gibt Ihrem Gerät jedoch die Möglichkeit, andere Dinge zu tun, während es wartet. Anweisungen zum Einstellen eines Interrupts finden Sie in Ihrem AVR-Datenblatt. Für Verzögerungen, die größer als der Interrupt-Zähler sind, können Sie einen Vorteiler oder eine andere Variable verwenden, um Interrupts zu zählen, bis die gewünschte Wartezeit aufgetreten ist.

2) Verwenden Sie ein NOP in einer for-Schleife, um Ihre Wartezeit auszuführen. Laut dieser Seite - http://playground.arduino.cc/Main/AVR - dauert eine NOP-Operation 1 Taktzyklus - 1 Taktzyklus = 1/Frequenz. Bei 16 MHz benötigt ein NOP 62,5 ns zur Ausführung. Verwenden Sie beim Definieren Ihres Schleifenzählers eine lange Variable ohne Vorzeichen , damit Sie nicht überrollen.

Ihr Schleifenzähler sieht so aus (volatile stellt sicher, dass die Kompilierung den Code nicht optimiert):

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

Bearbeiten: Es wird etwas Overhead von der for-Schleife geben. Sie können dies experimentell (einfach) oder durch Zählen der Anweisungen (schwer) ermitteln.

Ist das nicht der util/delayGrund (vgl. Gorloths Kommentar?)
Ja. Sie können auch util/delay verwenden. Interrupts sind die bevorzugte Methode, da dies durch eine verringerte erforderliche Frequenz und eine größere Geräteauslastung Strom spart. Die manuelle Codierung Ihrer Verzögerung ermöglicht auch eine bessere Optimierung.
Entschuldigung für die Unklarheit ... Ich frage mich, warum Sie Ihre Down-Delay-Funktion aufschreiben, anstatt die der Bibliothek zu verwenden? Ist das nicht wie selber schreiben strtok()oder malloc()? Sie wollen eine Warteschleife optimieren ? Ich denke, ob Interrupts bevorzugt werden oder nicht, hängt wirklich von Ihrer Anwendung ab. Viele Male brauchen Sie eine Sperrwartezeit, oder?
Die Optimierung bezieht sich hier nicht auf Geschwindigkeit, sondern darauf, den Code an Ihre Bedürfnisse anzupassen. Beispielsweise gibt die Funktion util/delay delay_us() an, dass die maximale Verzögerung 768 us / F_CPU in MHz beträgt. Was ist, wenn Sie länger verzögern möchten? Ein ähnliches Argument kann für die Funktion delay_ms() angeführt werden . Nur neugierig, wo würden Sie ein blockierendes Warten verwenden? Es ist besser, Ihr Gerät mit einem Weck-Interrupt in den Ruhezustand zu versetzen und Strom zu sparen.
Sie würden es dort verwenden, wo Strom kein Problem ist, wo die Kosten für Schlafen und Aufwachen zu hoch sind, wenn alle Ihre Timer / Unterbrechungen etwas anderes tun. Beim Bitbangen zum Beispiel sind blockierende Wartezeiten sehr nützlich.