avr-libc Versionen kleiner 1.6
Die Wartezeit der Funktion _delay_ms() ist auf 262,14ms/F_CPU (in MHz) begrenzt, d.h. bei 20 MHz kann man nur max. 13,1ms warten. Die Wartezeit der Funktion _delay_us() ist auf 768us/F_CPU (in MHz) begrenzt, d.h. bei 20 MHz kann man nur max. 38,4us warten. Längere Wartezeiten müssen dann über einen mehrfachen Aufruf in einer Schleife gelöst werden.
Beispiel: Blinken einer LED an PORTB Pin PB0 im ca. 1s Rhythmus
#include <avr/io.h>
#ifndef F_CPU
/* Definiere F_CPU, wenn F_CPU nicht bereits vorher definiert
(z. B. durch Übergabe als Parameter zum Compiler innerhalb
des Makefiles). Zusätzlich Ausgabe einer Warnung, die auf die
"nachträgliche" Definition hinweist */
#warning "F_CPU war noch nicht definiert, wird nun mit 3686400 definiert"
#define F_CPU 3686400UL /* Quarz mit 3.6864 Mhz */
#endif
#include <util/delay.h> /* in älteren avr-libc Versionen <avr/delay.h> */
/*
lange, variable Verzögerungszeit, Einheit in Millisekunden
Die maximale Zeit pro Funktionsaufruf ist begrenzt auf
262.14 ms / F_CPU in MHz (im Beispiel:
262.1 / 3.6864 = max. 71 ms)
Daher wird die kleine Warteschleife mehrfach aufgerufen,
um auf eine längere Wartezeit zu kommen. Die zusätzliche
Prüfung der Schleifenbedingung lässt die Wartezeit geringfügig
ungenau werden (macht hier vielleicht 2-3ms aus).
*/
void long_delay(uint16_t ms)
{
for(; ms>0; ms--) _delay_ms(1);
}
int main( void )
{
DDRB = ( 1 << PB0 ); // PB0 an PORTB als Ausgang setzen
while( 1 ) // Endlosschleife
{
PORTB ^= ( 1 << PB0 ); // Toggle PB0 z. B. angeschlossene LED
long_delay(1000); // Eine Sekunde warten...
}
return 0;
}
|
[Bearbeiten] avr-libc Versionen ab 1.6
_delay_ms() kann mit einem Argument bis 6553,5 ms (= 6,5535 Sekunden) benutzt werden. Wird die früher gültige Grenze von 262,14 ms/F_CPU (in MHz) überschritten, so arbeitet _delay_ms() einfach etwas ungenauer und zählt nur noch mit einer Auflösung von 1/10 ms. Eine Verzögerung von 1000,10 ms ließe sich nicht mehr von einer von 1000,19 ms unterscheiden. Ein Verlust, der sich im Allgemeinen verschmerzen lässt. Dem Programmierer wird keine Rückmeldung gegeben, dass die Funktion ggf. gröber arbeitet, d.h. wenn es darauf ankommt, bitte den Parameter wie bisher geschickt wählen.
Die Funktion _delay_us() wurde ebenfalls erweitert. Wenn deren maximal als genau behandelbares Argument überschritten wird, benutzt diese intern _delay_ms(). Damit gelten in diesem Fall die _delay_ms() Einschränkungen.
Beispiel: Blinken einer LED an PORTB Pin PB0 im ca. 1s Rhythmus, avr-libc ab Version 1.6
#include <avr/io.h>
#ifndef F_CPU
/* Definiere F_CPU, wenn F_CPU nicht bereits vorher definiert
(z. B. durch Übergabe als Parameter zum Compiler innerhalb
des Makefiles). Zusätzlich Ausgabe einer Warnung, die auf die
"nachträgliche" Definition hinweist */
#warning "F_CPU war noch nicht definiert, wird nun mit 3686400 definiert"
#define F_CPU 3686400UL /* Quarz mit 3.6864 Mhz */
#endif
#include <util/delay.h>
int main( void )
{
DDRB = ( 1 << PB0 ); // PB0 an PORTB als Ausgang setzen
while( 1 ) { // Endlosschleife
PORTB ^= ( 1 << PB0 ); // Toggle PB0 z. B. angeschlossene LED
_delay_ms(1000); // Eine Sekunde +/-1/10000 Sekunde warten...
// funktioniert nicht mit Bibliotheken vor 1.6
}
return 0;
}
|
|