www.mikrocontroller.net

Forum: Compiler & IDEs _delay_ms


Autor: ghost (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
HI!
Der folgende Programmabschnitt sollte eigentlich 1 - 20 Minuten warten 
und mir dann zwei kurze "Pulse" ausgeben.

Ich habe schon ewig nicht mehr C Programmiert und bin gerade am Anfang 
vom Microcontroller programmieren. Wo liegt der Fehler? Habe es auf 
einen ATmega168 programmiert und an die STK500 Dioden gehängt. Die 
blinken aber leider ohne die 1- 20 Minuten, die sie meiner Meinung nach 
durchgehend leuchten sollten.

    int i;
    long j;
    i = rand() % 20; // Generierung der "Pulsbreite"
    j = rand() % 20; // Generierung der Zeit zwischen zwei Pulsen
    j = j * 60000; // Umrechnung in Millisekunden
    _delay_ms(j); // Verzögerungszeit zwischen zwei Pulsen
    PORTB |= (1<<PB0); // PB0 auf high
    _delay_ms(i); // PB0 für 1-20 ms auf high
    PORTB &= ~ (1<<PB0); // PB0 wieder auf low
    PORTB |= (1<<PB1); // PB1 auf high
    _delay_ms(10); // PB1 immer für 10 ms auf high
    PORTB &= ~ (1<<PB1); // PB1 wieder auf low

Autor: ghost (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach ja das ganze liegt natürlich in einer Schleife, die immer wieder den 
Code durchläuft...

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ghost

>Der folgende Programmabschnitt sollte eigentlich 1 - 20 Minuten warten
>und mir dann zwei kurze "Pulse" ausgeben.

>Ich habe schon ewig nicht mehr C Programmiert und bin gerade am Anfang
>vom Microcontroller programmieren. Wo liegt der Fehler? Habe es auf
>einen ATmega168 programmiert und an die STK500 Dioden gehängt. Die
>blinken aber leider ohne die 1- 20 Minuten, die sie meiner Meinung nach
>durchgehend leuchten sollten.

>    int i;
>    long j;
>    i = rand() % 20; // Generierung der "Pulsbreite"
>    j = rand() % 20; // Generierung der Zeit zwischen zwei Pulsen
>    j = j * 60000; // Umrechnung in Millisekunden
>    _delay_ms(j); // Verzögerungszeit zwischen zwei Pulsen

Das geht schief. Das Makro verträgt max. 260 ms bei 1 MHz Prozessortakt. 
Bei 10 MHz entsprechd nur 26 ms. Das musst du als Schleife 
programmieren. Siehe Doku der libc.
Und nicht das vergessen

#define F_CPU 1000000UL

Logischerweise mit der richtigem Freqeunz in Hertz.

MfG
Falk


Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach ja, das Macro _delay_ms() sollte man auch nur mit Konstanten 
verwenden, denn es verlangt als Parameter einen double. Bei Variablen 
wird die Berechnung dann zur Laufzeit gemacht, was natürlich massiv Zeit 
und Programmspeicher kostet. Ein weiterer Gund, variable Verzögerungen 
übern ne Schleife zu programmieren.

MFG
Falk

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zitat aus der libc-Doku:
"When using _delay_us() and _delay_ms(), the expressions passed as 
arguments to these functions shall be compile-time constants, otherwise 
the floating-point calculations to setup the loops will be done at 
run-time, thereby drastically increasing both the resulting code size, 
as well as the time required to setup the loops."
Mit anderen (deutschen) Worten: Grundsätzlich nur Konstanten verwenden, 
die zur compile-Zeit bekannt sind.

Und wie Falk auch schon andeutete: In der Doku steht auch drin, welche 
maximalen Verzögerungen möglich sind (abhängig von der Taktfrequenz des 
Controllers). Zusätzlich muss dem Compiler natürlich bekanntgegeben 
werden (entweder im Makefile oder im AVRStudio unter Configuration 
Options) welche CPU-Frequenz verwendet wird.

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

Bewertung
0 lesenswert
nicht lesenswert
Außerdem nimmt man dafür Timer.

Autor: ghost (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also nehm ich am besten nen Timer direkt vom Microcontroller und lass 
den die Verzögerung ausführen?

Geht dann aber nichts mehr mit Zufall oder?

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ ghost

>Also nehm ich am besten nen Timer direkt vom Microcontroller und lass
>den die Verzögerung ausführen?

Ja, z.B. mit 10 ms.

>Geht dann aber nichts mehr mit Zufall oder?

DOCH! Einfach per rand() eine Zahl ermitteln und im Timerinterrupt 
runterzählen lassen.

MFG
Falk


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.