Forum: Compiler & IDEs Delay in AVR Studio


von norton (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich bin neu in der yC Welt und habe Probleme mit der _delay_ms(1) 
Funktion.
Ich verwende:
AVR Studio 4.13 Service Pack 2 Build 571 mit GCC
AVR ISP mkII Programmer
ATmega48

Ich möchte eine LED am PORTB zum blinken bringen und verwende folgenden 
Code:
1
#include <avr/io.h>
2
#ifndef F_CPU
3
#warning "F_CPU war noch nicht definiert!"
4
#define F_CPU 8000000UL
5
#endif
6
#include <util/delay.h>
7
 
8
void long_delay(uint16_t ms) {
9
    for(; ms>0; ms--) _delay_ms(1);
10
}
11
 
12
int main( void )
13
{
14
    DDRB = ( 1 << PB0 );        // PB0 an PORTB als Ausgang setzen
15
 
16
    while( 1 ) {                // Endlosschleife
17
        //PORTB = 0x00;      // Testeintrag1
18
        //PORTB = 0x01;      // Testeintrag2
19
        PORTB ^= ( 1 << PB0 );  // Toggle PB0 z.B. angeschlossene LED
20
        long_delay(1000);       // Eine Sekunde warten...
21
    }
22
 
23
    return 0;
24
}

Ich habe die Optimierung auf Os gestellt,
den Takt (F_CPU) richtig eingestellt,
und keine zu grossen Delaywerte laut delay.h verwendet.

Wenn ich das Programm übertrage blinkt die LED nicht. Wenn ich anstatt 
des Toggelns den Testeintrag1 oder Testeintrag2 verwende kann ich die 
LED ein bzw. ausschalten.
Es sieht so aus als würde das Programm nie über die Funktion 
long_delay() kommen. (alles was nachher kommt wird nicht mehr 
ausgeführt)

Ich hoffe jemand kann mir weiterhelfen. Mir fallen keine Möglichkeiten 
mehr ein was ich noch umstellen oder umkonfigurieren könnte.

Danke Norton

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


Lesenswert?

Richtigen CPU-Typ eingestellt?  Wenn du das z. B. für einen ATmega88
compilierst und linkst, wird der Stack ins Nirvana gesetzt und das
Dingens stürzt bei der Rückkehr aus der ersten gerufenen Funktion
ab.

von norton (Gast)


Lesenswert?

Habe ich überall (Projekt- und Programmer- Einstellungen) auf ATmega48 
eingestellt.

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


Lesenswert?

Es gibt keinen offensichtlichen Fehler darin.  Kannst du das ELF-File
mal posten?

von yalu (Gast)


Lesenswert?

Wie sicher bist du dir, dass der Controller tatsächlich mit 8 MHz
läuft? Man kann mit den Fusen auch sehr niedrige Taktraten einstellen.
Kontrolliere, falls noch nicht getan, die Inhalte der drei Fuse-Bytes.

von norton (Gast)


Angehängte Dateien:

Lesenswert?

Hier die Fuses Einstellungen

von norton (Gast)


Angehängte Dateien:

Lesenswert?

Hier habe ich das ELF File das das AVR Studio erstellt hat. Scheint aber 
sehr kryptisch zu sein.
Wie kommt man im normalfall zu diesem File?

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


Lesenswert?

Hmm, aber das stammt aus einer anderen C-Quelle als deine da oben,
nicht?  Ungefähr so:
1
#include <avr/io.h>
2
#ifndef F_CPU
3
#warning "F_CPU war noch nicht definiert!"
4
#define F_CPU 8000000UL
5
#endif
6
#include <util/delay.h>
7
8
void long_delay(uint16_t ms) {
9
    for(; ms>0; ms--) _delay_ms(1);
10
}
11
12
void LED_ein( void ) {
13
    PORTB = 0;
14
}
15
16
void LED_aus( void ) {
17
    PORTB = ( 1 << PB0 );
18
}
19
20
int main( void )
21
{
22
    DDRB = ( 1 << PB0 ) | ( 1 << PB1 ) | ( 1 << PB2 ) |
23
           ( 1 << PB4 );        // Bits 0, 1, 2 und 4 PORTB als Ausgang setzen
24
    PORTB = ( 1 << PB2 ) | ( 1 << PB3) |
25
            ( 1 << PB5 ) | ( 1 << PB6 ) | ( 1 << PB7);
26
27
    while( 1 ) {                // Endlosschleife
28
        PORTB = 0x00;      // Testeintrag1
29
        PORTB = 0x01;      // Testeintrag2
30
        //PORTB ^= ( 1 << PB0 );  // Toggle PB0 z.B. angeschlossene LED
31
        //long_delay(1000);       // Eine Sekunde warten...
32
    }
33
34
    return 0;
35
}

Mich interessiert aber vor allem das Ergebnis, wenn du long_delay()
auch wirklich rufst.

Die Stackinitialisierung für den ATmega48 stimmt übrigens.

von yalu (Gast)


Lesenswert?

Ach, guck an: Dein High-Fuse-Byte steht auf 0xCE, d.h. der Watchdog
ist an. Da in dein Programm mit dem Watchdog nichts macht, resettet er
den Controller jedesmal schon bevor der erste Delay abgelaufen ist.

Probier's mal mit dem Wert 0xDE.

von norton (Gast)


Lesenswert?

Habe den Watchdog abgeschaltet und funktioniert leider immer noch nicht.

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


Lesenswert?

Hast du danach auch einen power cycle gemacht?  Einen Wachhund, der
einmal gebissen hat, wird man so schnell nicht wieder los... nur
durch eine korrekte Behandlung oder einen power-on reset.

von norton (Gast)


Lesenswert?

Das Problem ist sicher der Watchdog, denn wenn ich in der long_delay() 
funktion den Watchdog resetiere funktioniert die Funktion.
1
void long_delay(uint16_t ms) {
2
    for(; ms>0; ms--)
3
  {
4
    _delay_ms(1);
5
    wdt_reset();
6
  }

Jetzt würde das ganze zwar funktionieren, aber ich würde trotzdem gerne 
wissen wie ich den Watchdog abschalten kann?
Wo muss ich ihn überall disablen und was muss ich wie reseten damit der 
Hund verschwindet?

Danke für die Hilfe!

von Karl H. (kbuchegg)


Lesenswert?

Es müsste eigentlich reichen, das Fusebit abzuschalten
und danach einmal Strom aus - Strom ein.

von Falk B. (falk)


Lesenswert?

@ norton (Gast)

>Jetzt würde das ganze zwar funktionieren, aber ich würde trotzdem gerne
>wissen wie ich den Watchdog abschalten kann?

Der ist bei den meisten AVRs normal ausgeschaltet. Einige können ihn per 
AVR Fuses einschalten.
Das Datenblatt ist dein Freund.

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.