mikrocontroller.net

Forum: Compiler & IDEs Anfänger: While-Schleife auf Atmega8


Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Tag,

ich bin relativ neu was Microcontroller angeht und habe mir nach der 
Anleitung auf

http://s-huehn.de/elektronik/avr-prog/avr-prog.htm

den seriellen Programmieradapter für den Atmega8 aufgebaut.

Das Testprogramm funktioniert einwandfrei, und jetzt wollte ich, bevor 
ich das GCC-Tutorial durchgehe, noch einmal meine Uralt-c-Kenntnisse 
auffrischen.

An PC0 und PC1 hängen 2 LEDs und die wollte ich ganz doof durch 2 
while-Schleifen, in denen auf 60000 gezählt wird, abwechseln ein- und 
ausschalten (Ich weiss, dass das Programm albern ist, aber es ging mir 
wie gesagt erstmal nur darum, ein paar Zeilen C zu schreiben).

Wenn
PORTC = ...  
 innerhalb der Schleifen steht, funktioniert das auch:
#include <avr/io.h>
#include <stdint.h>

int main (void) {

    uint64_t x=0,y=0;
    DDRC = 0xff;
   
while(1) {

    x=0;
        while (x<60000) {
                         x++;
                         PORTC = 0x00;   }


    y=0;
        while (y<60000) {
                         y++;
                         PORTC = 0xff;   }

        }
return 0;
}

wenn ich es jeweils danach ausführen lasse (was mir irgendwie sinnvoller 
erscheint), dann nicht mehr:

#include <avr/io.h>
#include <stdint.h>

int main (void) {

    uint64_t x=0,y=0;
    DDRC = 0xff;


while(1) {

    x=0;
        while (x<60000) {
                         x++;
                             }
PORTC = 0x00;

    y=0;
        while (y<60000) {
                         y++;
                             }
PORTC = 0xff;
          }
return 0;
}
Ich komme einfach nicht dahinter, woran es liegt.
Kann mir jemand auf die Sprünge helfen?

Viele Grüße!

Marc

Autor: M. H. (kroggy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Servus,
auch keine Ahnung. Versuch das mal so: volatile uint64_t x=0,y=0;

Eventl. Optimiert der Compiler da ein paar Sachen weg.

Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

danke, so funktioniert es!

Allerdings blinkt das Ganze jetzt viel langsamer als vorher. Ich würde 
eher das Gegenteilerwarten, weil doch jetzt pro Schleifendurchgang 
weniger Befehle ausgeführt werden...

Jemand eine Idee?

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> An PC0 und PC1 hängen 2 LEDs und die wollte ich ganz doof durch 2
> while-Schleifen, in denen auf 60000 gezählt wird, abwechseln ein-
> und ausschalten (Ich weiss, dass das Programm albern ist, aber es
> ging mir wie gesagt erstmal nur darum, ein paar Zeilen C zu
> schreiben).

Albern würde ich nicht sagen. Die blinkende LED ist das "Hello World" 
der Mikrocontroller-Programmierung. Da deine while-Schleifen nichts tun, 
außer Zeit zu verbrauchen, nimmt der Optimizer das als Gelegenheit, sie 
komplett zu entfernen, weil das Programm dann das gleiche macht, nur 
viel schneller (und das ist ja die Aufgabe des Optimizers). Du solltest 
lieber die delay-Funktionen der avr-libc verwenden.

Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Rolf, jetzt hat's 'klick' gemacht!
Schönen Abend wünsch ich euch beiden noch!

Marc

Autor: M. H. (kroggy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Langsamer ja,
liegt daran das es noch nie richtig funktioniert hat.

Grund: Optimierung.

Für Zeiten würde ich immer einen Timer nehmen, die delay Funktion kenne 
ich nicht.

Fürs basteln reicht es die Compiler Optimierungen ausschalten. Mit der 
Option -O0.
Alternative kannst solche schleifen Variablen auch global deklarieren, 
dann passiert da auch nichts.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt hab ich in der Eile noch die Erläuterung des Unterschieds der 
beiden Varianten vergessen. PORTC ist volatile. Das sagt dem Compiler, 
daß jeder Zugriff darauf, der im Code steht, auch wirklich ausgeführt 
werden muß. In der ersten Variante steht, daß die beiden Schleifen 
jeweils 60000 mal nach PORTC schreiben sollen. In der zweiten Variante 
kann die Schleife wegoptimiert werden, weil kein volatile-Zugriff 
erfolgt.

Daß es deutlich langsamer ist, wenn x und y volatile sind, ist klar. Zum 
einen muß der Schleifenzähler nicht nur geschrieben, sondern auch 
gelesen werden, zum anderen sind die Variablen vom Typ uint64_t und 
damit 8 mal so groß. Dadurch müssen jetzt pro Schleifendurchlauf 8 
Speicherstellen geschrieben und gelesen werden, statt nur eine zu 
schreiben.
Warum nimmst du eigentlich so einen riesigen Datentyp?

Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich hatte keine Ahnung, wie schnell so eine Schleife durchläuft, deshalb 
wollte ich wohl mit einer etwas größeren Zahl anfangen.
Nicht dass es so schnell geht, dass man nichts mehr wahrnehmen kann. 
Irgendwie so war wohl mein Gedanke...

Das mit delay hat übrigens funktioniert. Und danke auch nochmal für die 
weiteren Erklärungen - sehr hilfreich!

Grüße

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.