mikrocontroller.net

Forum: Compiler & IDEs Prescaler und Delay


Autor: norton (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich verwende einen ATmega48 und teile während des Programmablaufs die 
Clockfrequenz herunter (CLKPR) um Strom zu sparen.
Ist es nun möglich auch den F_CPU define zu verändern, damit die delay 
Funktionen in diesem Modus stimmen?
Oder muss ich dann beim delay den x- fachen wert verwenden um die 
richtige wartezeit zu bekommen?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein mit #define erzeugtes Makro ist nur für den Präprozessor von 
Bedeutung und existiert während des Programmablaufs nicht mehr. Deshalb 
kann man da auch nix dran ändern.

Wenn Du _delay_XX-Funktionen mit im Betrieb veränderlichen 
CPU-Takteverwenden willst, musst Du wohl oder übel in Phasen mit 
herabgesetztem Takt die Warteschleifen anpassen (Achtung: die Parameter 
der _delay-Aufrufe selbst müssen konstant und zur Compilerlaufzeit 
bekannt sein, sonst machen die Funktionen nicht das, was sie sollen!).

Wenn Du z.B. 2 ms warten musst und den Takt um einen Faktor 8 
runterteilst, dann könnte es z.B. so aussehen:
uint8_t n;

if(!(CLKPR & 0x0F)) //Prescaler 1?
    n = 8;
else
    n = 1;
for(uint8_t i = 0; i < n; i++)
    _delay_ms(1);
wobei F_CPU dann als die niedrigere Frequenz definiert sein muss.

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst das Makro schon 'ändern':
#define F_CPU 8000000L
//'schneller' Code
//...

#undef F_CPU //loesch das alte..
#define F_CPU 1000000L // setz neu
//etc...
Wenn du aber mal irgendwo den Überblick verlierst, welche Angabe gerade 
gilt.. ;)

hth. Jörg

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Ändern des Makros ist aber dann auf bestimtme Codeabschnitte 
bezogen, nicht auf bestimmte Zeiträume zur Laufzeit.
Das geht also nur gut, wenn du für hohen Takt und niedrigen Takt immer 
nur unterschiedlichen Code hast. Wenn du dieselbe Funktion einmal mit 
niedrigem und einmal mit hohem Takt durchlaufen willst, geht es nicht.
Ein Ausweg wäre ein eigenes Delay-Makro, sowas wie:
#define my_delay(time)          \
    do {                        \
         if (slow_clock)        \
             _delay_ms(time/8); \
         else                   \
             _delay_ms(time);   \
    } while (0)

Du mußt dir dann halt eine Variable slow_clock anlegen, mit der du dir 
merkst, ob du gerade hohen oder niedrigen Takt hast. Alternativ kannst 
du natürlich auch direkt CLKPR abfragen.

Autor: norton (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Hilfe!

Ich habe mich für die Variante von  @Rolf Magnus entschieden.
Ich lese mir den Wert des Prescalers aus und dividiere einfach den 
Delaywert durch den des Prescalers.

Gruss Norton

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
norton wrote:
> ich verwende einen ATmega48 und teile während des Programmablaufs die
> Clockfrequenz herunter (CLKPR) um Strom zu sparen.

Aha, Dein Gerät ist also batteriebetrieben.

Dann solltest Du besser die CPU ganz abschalten und per Uhrenquarz an T2 
wieder aufwecken.

Das Runtertakten bringt keine große Stromersparnis.


Peter

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
norton wrote:
> Danke für die Hilfe!
>
> Ich habe mich für die Variante von  @Rolf Magnus entschieden.
> Ich lese mir den Wert des Prescalers aus und dividiere einfach den
> Delaywert durch den des Prescalers.

Und damit dürften dann die Delay Zeiten alle falsch sein.
Welchen Teil des Satzes "Beim Aufruf von _delay_ms muss
die angegebene Zeit eine Konstante sein" hast du nicht
verstanden?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nö, Karl Heinz, da das Ganze ein Makro ist, löst der Compiler das
schon zur Compilezeit auf.

Autor: norton (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die weiteren Anregungen und Hilfestellungen.

@Karl Heinz
> Und damit dürften dann die Delay Zeiten alle falsch sein.

Da hast du recht, aber für eine blinkende LED ist das Zeitvertrödeln 
genau genug.
Ich werde mir für genaueres Timing die Timer reinziehen.


@Peter Dannegger
> Dann solltest Du besser die CPU ganz abschalten und per Uhrenquarz an T2
> wieder aufwecken.

Kannst du das bitte ein wenig genauer erörtern. Ich fange gerade erst 
mit uC programmieren an und habe das nicht ganz verstanden. (Ich nehme 
an, wenn ich die CPU ganz abschalte kann ich keine Programmfunktionen 
(zb.: eintreten in den Aktivbereich) ausführen?)

Norton

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> (Ich nehme an, wenn ich die CPU ganz abschalte kann ich keine
> Programmfunktionen (zb.: eintreten in den Aktivbereich) ausführen?)

Das ist richtig. Die CPU muß durch einen entsprechenden Interrupt erst 
aufgeweckt werden. Wie Peter schon schreibt, kannst du einen Timer auch 
mit eigenem Takt versorgen und diesen dann nutzen, um den Prozessor nach 
einer bestimmten Zeit aufzuwecken. Dann kann er schauen, ob's was zu tun 
gibt, das dann ggf. machen, dann sich wieder schlafen legen bis zum 
nächsten Timer-Event. Auch das Aufwecken z.B. über einen Taster an einem 
Interrupt-Pin ist möglich.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.