Ich habe gerade angefangen, auf ARM zu programmieren, ich hatte einige Erfahrung mit AVR, aber nicht so viel. Die Frage ist wahrscheinlich zu trivial, aber das Material über ARM ist zu wenig im Netz ... sorry trotzdem.
Ich weiß, dass wir für die Implementierung von Verzögerungen in ARM Timer oder Busy-Loops verwenden können. Ich habe diese Methoden ausprobiert. Aber einer meiner Freunde schlägt vor, dass es eine "delay.h"-Headerdatei für arm gibt, die alle notwendigen Verzögerungsfunktionen enthält, genau wie avr, delay_ms und ... .
Zunächst einmal, so dumm diese Frage auch klingen mag, gibt es wirklich eine eingebaute Verzögerungsfunktion in der ARM-Programmierung. Ist es in delay.h?
Wenn ja, warum ist die Verwendung von Timern zur Implementierung von Verzögerungen so beliebt? Warum verwenden sie nicht einfach die eingebaute Funktion?
Ich studiere die LPC17xx-Serie.
Viele Compiler und Bibliotheken unterstützen die ARM-Familie. Ich würde keine Zeit damit verschwenden, nach einer einzelnen Lösung zu suchen, die in einem einzelnen Dateinamen definiert ist. Das ist sicher nicht „die“ Lösung für „ARM“.
Wie bei AVR und den meisten anderen Prozessoren, sicherlich Mikrocontrollern, haben Sie die Wahl, in einer Vordergrundschleife entweder eine kalibrierte Schleife zu verwenden oder einen Timer abzufragen. Sie können bei Bedarf auch einen Timer-basierten Interrupt verwenden. Es hängt davon ab, wofür Sie eine Verzögerung durchführen müssen und was sonst noch während dieser Verzögerung vor sich gehen könnte. Abhängig von dem spezifischen Chip und der Zeitspanne, die Sie verzögern möchten, können Sie den Chip möglicherweise für diesen Zeitraum in den Ruhezustand versetzen.
Wenn Sie eine Bibliothek für andere Dinge wie SPI, I2C usw. für den Zielprozessor und die Toolchain verwenden, haben Sie wahrscheinlich auch Timer-Routinen und können diese einfach verwenden. Wenn Sie Ihre eigenen rollen (am portabelsten, aber auch am meisten Arbeit), dann schauen Sie sich die Timer an. Auf lange Sicht wird es einfacher sein, Code zu warten, der auf einem Timer basiert, anstatt auf einer kalibrierten (Count to N) Schleife .
Es gibt eine Reihe von Toolchains und Bibliotheken, die speziell auf die NXP LPC-Familie zugeschnitten sind, wenn Sie diesen Weg einschlagen möchten.
In keiner Weise, Gestalt oder Form. Gibt es eine einzige Lösung, auf die Sie sich beschränken sollten? Nicht für ARM, nicht für AVR, nicht für einen von ihnen.
Manchmal wird Code in einem Kontext ausgeführt, in dem sonst nichts passiert. Wenn der Prozessor ein E/A-Bit setzt, dann eine Reihe von Anweisungen ausführt, die insgesamt 1 ms zur Ausführung benötigen, und dann das E/A-Bit löscht, dann pulsiert die von diesem Bit gesteuerte Leitung für 1 ms hoch. Einfache Verzögerungsverfahren können in solchen Zusammenhängen nützlich sein. Sie sind jedoch weit weniger nützlich in Kontexten, in denen andere Dinge vor sich gehen können. Wenn während der oben genannten Verzögerung ein Interrupt auftritt, der 100 us für den Service benötigt, wird der Pin für 1,1 ms statt 1 ms hoch gepulst. Schlimmer noch, wenn man versucht, eine solche Verzögerung in einer Interrupt-Serviceroutine zu verwenden, werden der Hauptleitungscode und alle Interrupts mit niedrigerer Priorität ausgesetzt, bis eine solche Verzögerung abgeschlossen ist.
Im Allgemeinen ist der oben genannte Ansatz zur Implementierung geeignet, wenn entweder (1) man so etwas wie einen Bootloader schreibt, der in der Lage sein sollte, ohne Interrupts zu arbeiten, und nichts anderes passiert, während er läuft; (2) man braucht eine Verzögerung, die ausreichend kurz ist, es macht keinen Sinn, zu versuchen, etwas anderes zu tun. Wenn man beispielsweise einen 32-MHz-Prozessor verwendet, um mit einem Gerät zu kommunizieren, das 1,6 us Leerlaufzeit zwischen Datenbytes benötigt, würde das Einfügen von Code, der 52 Zyklen damit verbringt, nichts zu tun, bedeuten, dass der ARM gut positioniert sein könnte, um das nächste Byte um 1,6 zu senden uns später. Wenn der ARM dagegen versucht, etwas anderes zu tun, wäre er wahrscheinlich am Ende von 1.6us damit beschäftigt und würde das nächste Byte erst einige Zeit später senden.
Stellen Sie sich eine ARM-CPU als eine vollwertige CPU vor, die Sie für ein Betriebssystem wie Linux verwenden könnten. Stellen Sie sich nun vor, was passieren würde, wenn Sie die Ausführung auf dem gesamten Chip blockieren würden, wann immer Sie eine Zeitverzögerungsfunktionalität wünschen. Das Ganze würde während der Verzögerung abstürzen, was zu einer völlig unbrauchbaren Erfahrung für jede Art von benutzerinteraktivem System führen würde. Deshalb werden Timer bevorzugt.
Timer sind nützlich, weil sie die Blockierungssituation vermeiden. Die CPU fährt mit der Ausführung von Code fort und springt zurück zu einer Handler-Routine, sobald der Zeitgeber abgelaufen ist. Dies bietet eine Form des asynchronen Betriebs, der einen viel flexibleren Code ermöglicht.
In Architekturen, die interne Zeitgeber nicht direkt unterstützen, aber externe Interrupts unterstützen, kann ein externes Zeitgebergerät verwendet werden. Der Timer ist mit einem Zeitversatz (normalerweise ein Skalar und Multiplikator) und einer Unterbrechungsnummer programmiert. Wenn der externe Timer den Interrupt auslöst, liest die CPU eine Interrupt-Tabelle, um den Interrupt-Vektor zu finden , der eine lineare Adresse ist, an die die Ausführung übertragen wird, um das Timer-Ereignis zu handhaben.
Es ist natürlich möglich, einen ARM-Prozessor für eine einfache Verzögerung zu verwenden. Siehe meinen Code unten. Je nachdem, wofür Sie Ihren Prozessor sonst noch benötigen, ist dies jedoch möglicherweise nicht die beste Lösung. Dieser Code läuft auf einem Prozessor der LPC2000-Serie von NXP.
/**********************************************************************/
/* Timer.c */
/* Implements a delay : */
/* TMR0 is a mcrosecond timer capable of timing events of upto */
/* 4294.967295 seconds (1 hour 11 min 36.967295 sec) */
/* includes both delay and stop watch functions */
/* void Delay(unsigned int delay); delay in microseconds */
/* Does not use interupts. Note timer may rollover during delay */
/* so code checks for this */
/* Note: delay is minimum delay as interupts can slow it down */
/**********************************************************************/
/*
* Note: Assumes TMR0 is already setup with 1 microsecond tick
*/
#include <LPC2103.h>
#include "Timer.h"
void Delay(unsigned int delay){
unsigned int start;
unsigned int stop;
unsigned int now;
start = T0TC;
stop = start + delay + 1; /* +1 because call could arrive just
before TOTC changes */
if (stop > start){ /* usually is */
do{
now = T0TC;
}while (now < stop && now >= start); /* Catch timer roll-over as done */
}else{ /* Need timer to roll over */
do{
now = T0TC;
}while (now < stop || now >= start);
}
}
Selbst wenn Sie gerne nur in einer Schleife sitzen und auf eine Verzögerung warten, ist ein Timer möglicherweise besser, da es mit einer einfachen Schleife wie z. B. schwieriger ist, Verzögerungszeiten abzuschätzen
for(i=1000; i >0; i--){
;
}
Weil ein guter optimierender Compiler dies einfach optimieren kann.
Selbst wenn es nicht optimiert wird, ist es schwierig, genau zu wissen, wie lange diese Verzögerung dauern wird, da die Prozessoren der NXP LPC-Serie Speicherbeschleuniger haben und der Prozessor Pipe-Lining hat.
for(volatile int i=1000; i >0; i--) ;
Polynom
Christa K
Polynom
Christa K
for()
Schleifenzahl von 100 gesehen und der Kommentar sagte, es sei eine Verzögerung von 10 us.Chris Stratton