Hallo zusammmen,
ich hoffe jemand kann mir bei meinem Problem weiterhelfen. Habe schon
diverse Foren durchsucht, aber leider nichts passendes gefunden.
Ich möchte über einen ATMega8, welchen ich unter AVR Studio programmiere
(Compiler ist der Gnu Compiler) zwei LED´s auf meinem
Funk-Evaluationsboard von Pollin als Wechselblinker betreiben.
Hier mal der Quellcode:
#define F_CPU 12000000
#include <avr/io.h>
#include <stdio.h>
#include <inttypes.h>
#include <stdint.h>
#include <util/delay.h>
int a, b, c, d;
int main()
{
while(1)
{
PORTD = (1<<PD5); // LED1 an
for (a=1; a<=1000; a++) // warte eine gewisse Zeit
{
for (b=1; b<=10000; b++)
{
}
}
PORTD = (1<<PD6); // LED2 an
for (c=1; c<=1000; c++) // warte eine gewisse Zeit
{
for (d=1; d<=10000; d++)
{
}
}
}
Kurz zum Programm:
In einer Endlosschleife soll zuerst PD5 auf High gesetzt werden, somit
ist LED1 an, danach wird via zweier for-Schleifen eine gewisse Zeit
gewartet und danach das ganze für LED2 wiederhohlt. Somit sollte sich
ein Wechselblinker ergeben. Zeitwerte müssten noch angepasst werden,
damit man auch was sieht...
Wenn ich den Code Compiliere und ihn unter AVR Studio durchlaufen lasse,
so lässt er die for-Schleifen immer aus, als ob sie nicht da wären und
springt somit von LED1 nach LED2 setzen hin und her, sodass beide LED´s
"dauerhaft" an sind.
Habe auch schon mit Freunden und Dozenten darüber geschaut, jedoch hatte
keiner eine Antwort.
Kann es sein, dass der Compiler die Schleifen einfach wegoptimiert, da
hier "nichts" gemacht wird?
Mir ist bewusst, dass es viele bessere Möglichkeiten gibt einen
Wechselblinker zu programmieren, jedoch hätte ich es zur Übung gerne auf
diese Art geschafft.
Ich hoffe, dass meine Angaben soweit verständlich sind, da ich absoluter
Neuling auf dem Gebiet bin.
Zander
Nun, da in den Schleifen keine Befehle abgearbeitet werden, wird der
Compiler sie schlicht wegoptimieren. Setz doch mal ein delay_ms(1) in
die Schleifen.
Besser wär's aber, Du schaust Dir im Tutorial mal das Kapitel über Timer
an...
Der compiler optimiert die Schleifen weg, weil da nichts drin steht.
Loesung: optimierung aussschalten oder den compiler zwingen, in den
Schleifen was zu machen, zB ne volatile variable den aktuellen
Schleifenzehlerwert annehmen lassen.
@Micha B.
über die delay_ms-Funktion funktionierts, das hatte ich schon
getestet...
@Matthias:
Hab leider keine Ahnung wo ich die Optimierung aussschalte, bzw. was
eine "volatile" ist.
@zander
es geht darum, dass überhaupt etwas in den Schleifen drin steht. Das
delay_ms war lediglich ein Beispiel.
Sonst nimm halt das 'asm volatile("nop")' welches der mechatroniker
vorgeschlagen hat.
Zander wrote:
> @Micha B.> über die delay_ms-Funktion funktionierts, das hatte ich schon> getestet...
Warum willst Du dann die optimale, genaue und compilermäßig einwandfreie
Lösung durch ne inkompatible, ungenaue Krücke ersetzen ???
Wenn Du das Delay änderbar haben willst, dann nimm ein definiertes Delay
(z.B. 1ms) und mach ne Schleife (n * 1ms) drumrum.
Peter
Mit volatile kannst du den compiler zwingen, eben jenen mit volatile
markierten Befehl definitiv auszufuehren, auch wenn sein optimierer
sagt, dass es keinen sinn macht. Macht man zB, wenn in Interfaces zu
bestimmten Zeiten Register gelesen werden muessen, obwohl mit dem Wert
rein gar nichts zu machen ist. Aber um sicherzustellen, dass das
Register, warum auch immer, gelesen wird, markiert man das mit volatile.
in deinem fall ginge sowas:
Matthias wrote:
> Mit volatile kannst du den compiler zwingen, eben jenen mit volatile> markierten Befehl definitiv auszufuehren,volatile hat nichts mit Befehlen zu tun, zumal es in C keine "Befehle"
in dem Sinne gibt. volatile ist ein sogenannter Typqualifizierer.
volatile (auf deutsch "flüchtig") besagt lediglich, dass die so
gekennzeichnete Variable sich außerhalb des Zugriffsbereichs des
Compilers bzw. des eigentlichen Programms ändern kann (z.B. durch ein
asynchron auftretendes Hardware-Ereignis, einen Interrupt). Zugriffe auf
normale Variablen, die nur vom Programm selbst geändert werden, können
weggelassen werden, wenn der Compiler sieht, dass sich die Variable seit
dem letzten Zugriff gar nicht geändert haben kann oder einfach nicht
weiter verwendet wird (und das ist genau das, was in Zählschleifen
passiert, da mit dem Wert der Variablen gar nichts weiter gemacht wird
und der Compiler so den aus seiner Sicht überflüssigen Code
rausschmeißt). Ist eine Variable mit dem Typqualifizierer volatile
versehen, dann weiß der Compiler, dass er alle Zugriffe auf das Objekt
durchführen muss, da es sein kann, dass die Variable von außen verändert
wird oder dass ihr Wert von außerhalb des Programms benötigt wird.
Ein gutes Beispiel für die (für den Programmierer allerdings versteckte)
Anwendung von volatile ist die Definition der I/O-Register der
Mikrocontroller (die ja für den Compiler letztendlich auch nur
irgendwelche Variablen bzw. Speicherstellen darstellen, denn der
Compiler kennt ja den Aufbau des Controllers nicht), die allesamt intern
als volatile qualifiziert sind.
Danke an alle für die Antworten, ihr habt mir damit sehr weitergeholfen.
@Peter Dannegger
Auch wenns so ne Krücke ist, hab ich jetzt doch wieder was dazugelernt.
Darum gehts doch ;-)
Zander
Grundsätzlich
Mit FOR schleifen eine Zeitbasis zu schaffen ist so ziemlich die
ungeignetste Möglichkeit.
Das Zeitverhalten ist unkalkulierbar, und das sogar im extremen wenn
Interrupts genutzt werden.
Für Wartezeiten IMMER einen Hardware Timer nutzen, alles andere ist
Müll.
Hallo,
mit FOR-Schleifen eine "Zeitbasis" zu schaffen ist vermutlich der
einfachste Weg zu einer Verzögerung zu kommen.
Weder genau noch elegant, für einen Anfänger aber wohl ideal
verständlich.
Ich habe früher (tm) jemandem, der irgendwie programmieren auf einem C64
in Basic lernen wollte, damit beschaftigt, daß er eine Uhr programmieren
sollte.
Keine genau gehende sondern eine überhaupt gehende.
Brachte Verständbis für For-Next-Schleifen, für If-Then-Abfragen, für
Ausgaben mit Print.
Dann um ein brauchbares Ausgabeformat gebeten, also mit : dazwischen und
führenden Nullen, wenn nötig.
Damit waren Strinvormatierungen ziemlich gut zu erschlagen.
Dann konnte man über genaue Laufzeiten nachdenken.
Wenn ein Anfänger eine LED blinken lassen will, dann soll diese doch
bitte erstmal blinken. Was nutzt ihm der Kampf mit dem Timer und seinen
Problemen, wenn er letztlich nichts davon zu sehen bekommt.
Nur so als Gedankengang...
Gruß aus Berlin
Michael