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
1
PORTC=...
innerhalb der Schleifen steht, funktioniert das auch:
1
#include<avr/io.h>
2
#include<stdint.h>
3
4
intmain(void){
5
6
uint64_tx=0,y=0;
7
DDRC=0xff;
8
9
while(1){
10
11
x=0;
12
while(x<60000){
13
x++;
14
PORTC=0x00;}
15
16
17
y=0;
18
while(y<60000){
19
y++;
20
PORTC=0xff;}
21
22
}
23
return0;
}
wenn ich es jeweils danach ausführen lasse (was mir irgendwie sinnvoller
erscheint), dann nicht mehr:
1
#include<avr/io.h>
2
#include<stdint.h>
3
4
intmain(void){
5
6
uint64_tx=0,y=0;
7
DDRC=0xff;
8
9
10
while(1){
11
12
x=0;
13
while(x<60000){
14
x++;
15
}
16
PORTC=0x00;
17
18
y=0;
19
while(y<60000){
20
y++;
21
}
22
PORTC=0xff;
23
}
24
return0;
25
}
Ich komme einfach nicht dahinter, woran es liegt.
Kann mir jemand auf die Sprünge helfen?
Viele Grüße!
Marc
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?
> 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.
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.
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?
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
Eine eigene Frage?
Dieser Thread ist über 17 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.