Wie funktioniert die Funktion delayMicroseconds ()? Soweit ich weiß, ist der Vorteiler von timer0 auf 64 eingestellt. Für einen 16-MHz-Takt ergibt sich ein Wert von 4,0 us pro Zählung. Ich bin ein bisschen verwirrt in der Mathematik, um das 1uS-Intervall zu erreichen?
8
micros()
heißt es: "Auf 16-MHz-Arduino-Karten (z. B. Duemilanove und Nano) hat diese Funktion eine Auflösung von vier Mikrosekunden (dh der zurückgegebene Wert ist immer ein Vielfaches von vier)."Antworten:
Der Quellcode für diese Funktion ist ziemlich gut dokumentiert und befindet sich unter /usr/share/arduino/hardware/arduino/cores/arduino/wiring.c auf Linux-Systemen. Windows-Systeme haben einen ähnlichen Pfad wie die Datei wiring.c. Bemühen Sie sich, die Datei zu finden und zu durchsuchen. Konzentrieren Sie sich vorerst nur auf diese einzelne Funktion, sie basiert nicht auf anderen Funktionen.
Wenn Sie den Code überprüfen, werden Sie feststellen, dass es nicht um Timer geht, sondern um Befehlszyklen. Der Code hängt stark davon ab, dass die Compileroptimierung für Sie genauso ist wie für den Entwickler der Bibliothek. Das ist eine Annahme des Autors! Die Anzahl der von jedem Befehl 'verbrannten' CPU-Zyklen ist im Atmel AVR-Befehlssatzdokument gut dokumentiert .
Zuerst wird geprüft, ob der Verzögerungswert gleich 1 ist, in diesem Fall wird nur von der Routine zurückgekehrt, die bereits über eine Mikrosekunde CPU-Zeit verbracht wurde.
Dann wird der Verzögerungswert mit vier (
<<=2
) multipliziert . Die__asm__
-loop wird in eine 4-CPU-Zyklusschleife kompiliert. 4 Zyklen × 4 = 16 Zyklen. 16MHz / (4 × 4) = 1MHz, was 1 us Zykluszeit benötigt, die Auflösung, nach der wir suchen.Die letzten -2 Mikrosekunden (bevor die Schleife gestartet wird) sind wieder eine Korrektur des vom Overhead eingeführten Compilers. Das Aufrufen von
__asm__
-code von C erfordert einige zusätzliche Anweisungen zum Speichern von CPU-Registern.Für ein normales Arduino bei 16 MHz wird nur der folgende Code kompiliert:
Übrigens: Der kompilierte Code ist ziemlich genau, aber beachten Sie Folgendes: Auf Arduino sind zeitgesteuerte Interrupts konfiguriert, von denen die meisten nichts wissen. Wenn während der Ausführung von ein Interrupt empfangen wird
delayMicroseconds()
, ist das Timing vondelayMicroseconds()
falsch. Sie können Interrupts natürlich vor dem Aufruf stoppendelayMicroseconds()
und anschließend aktivieren, dies wirkt sich jedoch wiederum auf die Timing-Genauigkeit durch die Dauer des kompilierten Codes zum Aktivieren / Deaktivieren aus.quelle