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
Diese Zeile:
1 | 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. Richtig wäre z.B.:
1 | Zaehler++; |
oder
1 | Zaehler = Zaehler+1; |
PS: Quelltexte sollte man hier im Forum mit
1 | [c] |
2 | ... |
3 | [/c] |
formatieren.
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 | unsigned char Zaehler; // Up/Down-Zähler (0-255) |
6 | |
7 | // --- Hauptprogramm ---
|
8 | int main (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:
1 | volatile unsigned char Zaehler; // Up/Down-Zähler (0-255) |
Abgesehen davon hast du dein _delay_ms() nicht mehr drin.
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:
1 | #include <avr/io.h> |
2 | #include <stdint.h> |
3 | #include <util/delay.h> |
4 | |
5 | // Variablen definieren
|
6 | volatile unsigned char Zaehler; // Up/Down-Zähler (0-255) |
7 | |
8 | // --- Hauptprogramm ---
|
9 | int main (void) |
10 | {
|
11 | // Pins definieren
|
12 | 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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.