Hallo,
wie schon die Überschrift meines Beitrages verrät, bin ich gerade am
AVR-GCC "lernen".
Vorauskenntnisse bringe ich aus der PC-Programmierung mittels Basic und
Pascal und aus der "C-Control I M-Unit 2"-Programmierung mittels CCBasic
und BasiC++ mit.
Ich benutze das AVR Studio 4.18 zur Programmierung und habe bereits ein
sehr einfaches Projekt mit AVR-GCC erfolgreich programmiert und im
Einsatz.
Jedoch stehe ich jetzt seit Tagen schon vor einem mir unlösbaren
Problem. Die Suche in diversen Tutorials und Google hat nichts zur
Lösung beigetragen, daher schreibe ich nun diesen Beitrag.
Nun aber zum Projekt selbst (eigentlich auch ganz einfach - aber derzeit
nicht für mich):
Ich habe zwei Taster (schalten nach Masse). Drücke ich den einen Taster,
soll eine Variable um 1 hoch gezählt werden; drücke ich den Anderen,
soll die selbe Variable um 1 herunter gezählt werden.
Bevor ich aber die Taster interplementieren wollte, wollte ich zuerst
ein ganz einfaches Testprogramm schreiben, welches einfach in einer
Schleife die Variable hochzählt:
>#include <stdint.h>>#include <util/delay.h>>>unsigned char Zaehler;>>int main (void)>{>while (1)>{>Zaehler = Zaehler++;>_delay_ms_(1000);>}>}
Lasse ich die Schleife "while (1)" weg, so wird die Variable Zähler
tadellos von 0 auf 1 erhöht. Will ich aber, dass die Variable alle 1
Sekunde um 1 erhöht wird, so wird einfach der Ausdruck "Zaehler =
Zaehler++;" übersprungen und das Programm nach 1 Sekunde beendet.
Wo liegt hier mein (Denk-)Fehler? Die "While"-Schleife funktioniert(e)
auch ohne "Return"-Befehl bei meinem letzten Projekt.
Es wäre toll, wenn Ihr mir einen kleinen Tipp geben könntet, warum mir
der Debugger die Variable nicht erhöht...
Vielen Dank und Grüße,
Black
Hallo,
danke für die schnelle Antwort.
Was ich vielleicht noch erwähnen sollte (habe ich leider vergessen) ist,
dass ich einen ATTiny2313-20PU mit "AVR Simulator" im AVR Studio 4.18
programmiere.
Ich habe mal meinen Quelltext geändert:
1
#include<avr/io.h>
2
#include<util/delay.h>
3
4
// Variablen definieren
5
unsignedcharZaehler;// Up/Down-Zähler (0-255)
6
7
// --- Hauptprogramm ---
8
intmain(void)
9
{
10
while(1)// Endlosschleife
11
{
12
Zaehler++;// Zaehler um 1 erhöhen
13
}
14
}
Wenn ich nun Compiliere und Debugge, dann bleibt der Pfeil (welcher die
aktuell verarbeitete Codezeile anzeigt) bei der ersten "{" stehen - egal
wie oft ich auf "Step into next statement" klicke.
Die Variable "Zaehler" bleibt bei ihrem Wert "0".
Normalerweise sollte der Debugger doch in die Schleife springen und
jedes mal bei Drücken von "Step into next statement" die Variable
"Zaehler" um 1 erhöhen... tut er aber nicht - was habe ich hier falsch
gemacht?
Weitere Hinweise und Tipps wären super !
Vielen Dank und Grüße,
Black
Ich vermute, daß der Compiler so schlau ist zu merken, daß
Zaehler nie mehr verwendet wird und deshalb die Rechnerei
einfach wegoptimiert.
Falls ja, sollte es helfen, die Variable so zu definieren:
Klaus Wachtler schrieb:> Diese Zeile: Zaehler = Zaehler++;> erhöht erst Zaehler um 1 (wegen des ++) und weist an Zaehler> dann den alten Wert zu, womit die Variable wieder den alten Wert> hat.
Nicht unbedingt Nach ISO-C ist das Verhalten undefiniert. In welcher
Reihenfolge diese Operationen durchgeführt werden, ist nicht festgelegt.
Black Zero schrieb:> Wenn ich nun Compiliere und Debugge, dann bleibt der Pfeil (welcher die> aktuell verarbeitete Codezeile anzeigt) bei der ersten "{" stehen - egal> wie oft ich auf "Step into next statement" klicke.> Die Variable "Zaehler" bleibt bei ihrem Wert "0".
Der Compiler hat erkannt, daß in der Schleife die Variable nicht benutzt
wird und die Schleife nie verlassen wird. Also hat der Optimizer das
Inkrementieren entfernt, weil es nicht benötigt wird.
Rolf Magnus schrieb:> Nicht unbedingt Nach ISO-C ist das Verhalten undefiniert. In welcher> Reihenfolge diese Operationen durchgeführt werden, ist nicht festgelegt.
ja, und damit aus 2 Gründen falsch: 1. weil es undefiniert ist und
2. weil es mit gcc offenbar nicht geht.
Hallo,
jetzt funktioniert es, so wie es soll.
Anscheinend war es die kombination aus dem "Zaehler = Zaehler++;" und
dem "unsigned char Zaehler".
Das "_delay_ms(1000);" hab ich vergessen mit zu posten, da ich bein
Debuggen diesen immer auskommentiere, sonst muss ich mit Sprungmarken
arbeiten, da ich sonst ewig lange "Step into next statement" drücken
müsste...
So lautet nun der funktionierende Code:
DDRB=0xff;// PortB (0-7) als Ausgang definieren (LEDs)
13
14
// Programm
15
while(1)// Endlosschleife
16
{
17
Zaehler=Zaehler+1;// Zaehler um 1 erhöhen
18
PORTB=Zaehler;// Zahl an PortB Binär ausgeben
19
_delay_ms(1000);// 1 Sekunde warten
20
}
21
}
Ich habe bereits eine kleine Anzeige mittels 8 LEDs interplementiert,
damit der Code einen kleinen Sinn ergibt.
Übertragen auf den ATTiny, macht dieser auch das, was er soll (ist bei
mir nicht immer der Fall gewesen).
Vielen Dank für die tolle Hilfe!
Grüße,
Black
Black Zero schrieb:> // Programm> while (1) // Endlosschleife> {> Zaehler = Zaehler+1; // Zaehler um 1 erhöhen> PORTB = Zaehler; // Zahl an PortB Binär ausgeben> _delay_ms(1000); // 1 Sekunde warten> }> }
Bei diesem Code bräuchtest du das volatile allerdings nicht mehr. Das
hast du vorher ja nur gebraucht, weil dein Zähler für nichts mehr
verwendet wurde. Jetzt wird sein Wert aber in jedem Durchauf nach PORTB
geschrieben, welches selbst schon volatile ist (wie sämtliche
I/O-Register).
Rolf Magnus schrieb:> Bei diesem Code bräuchtest du das volatile allerdings nicht mehr. Das> hast du vorher ja nur gebraucht, weil dein Zähler für nichts mehr> verwendet wurde. Jetzt wird sein Wert aber in jedem Durchauf nach PORTB> geschrieben, welches selbst schon volatile ist (wie sämtliche> I/O-Register).
Vielen Dank für den Hinweis !
Außerdem solltest du die Variable Zähler nicht global machen,
gewohn dir so was gleich wieder ab sie wird nur in der main Funktion
gebraucht also sollte sie auch dort definiert werden.
Glaube mir es macht das Debuggen sehr viel einfacher wenn Variablen nur
in denn Kontext definiert sind in dem du sie brauchst in deinen Fall in
der Funktion main.
Wenn die Projekte mal größer werden solltest du die externe Variable
wenigsten static machen so das du sicher sein kannst das externe
Variablen nur innerhalb der Datei existieren.
Noch ein kleiner Hinweis: Es ist sinnvoll sich von Anfang an
anzugewöhnen alle Variablen zu Beginn der Verwendung sauber zu
initialisieren. Damit eliminierst du eine häufige Fehlerquelle ;)
MfG
Stefan