Forum: Compiler & IDEs _delay_ms


von ghost (Gast)


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

von ghost (Gast)


Lesenswert?

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

von Falk (Gast)


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


von Falk (Gast)


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

von johnny.m (Gast)


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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Außerdem nimmt man dafür Timer.

von ghost (Gast)


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?

von Falk (Gast)


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


Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.