www.mikrocontroller.net

Forum: Compiler & IDEs AVR-GCC if Abfrage funktioniert nicht


Autor: Ben (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo miteinander,

derzeit entwickle ich ein Programm für einen ATTiny2313 das Daten von 
einer RS232 Schnittstelle empfängt und an einem LCD ausgibt.

Aus dem Datenstrom werden sechs Werte ausgelesen und am LCD ausgegeben.

Auszug aus dem Code:
...
else if(state>12 && state<17 && count==2)count=3;
else if(state>4 && state<10 && count==0)count=1; //Ich denke hier liegt der Fehler

switch(count){
case 3:
 //hier wird der gerade per USART empfangene Wert am LCD ausgegeben
 count++;
 break;
case 1:
 //hier wird der gerade per USART empfangene Wert am LCD ausgegeben
 count++;
 break;
}
Hin und wieder setzt die else if Anweisung count auf 1, obwohl die 
Variable state den Wert 2 hat. (siehe zweite Zeile im Code)

Wenn ich den Wert von state ein zweites mal prüfe, funktioniert das 
Programm so wie es soll:
else if(state>4 && state<10 && count==0) if(state>4)count=1;

Hat jemand eine Idee warum die zweite else if Abfrage ausgeführt wird, 
obwohl die Bedingung state>4 unwahr ist?

Folgendes hab ich schon probiert:
-Das Programm angehalten sobald die zweite else if Anweisung ausgeführt 
wird und der Wert von state==2 ist. Damit sollte sichger gestellt sein 
das die Variable count nicht irgendwo anders geändert wird
-Andere Frequenzen und Controller (atmega8515) verwendet
-die Variable state auf dem lcd ausgegeben (ist im Fehlerfall immer 2)

Viele Grüße
Ben

: Verschoben durch Moderator
Autor: Kai S. (zigzeg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich denke Dein Problem liegt ganz woanders. Kann man aber nicht viel zu 
sagen, da wir ja den Rest des Codes nicht kennen. Gibt es vielleicht 
eine Interrupt-Routine die state veraendert ?

ZigZeg

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, wie soll da irgendjemand was zu sagen???

... ist kein C-Code. Ohne ein übersetzbares Modul und Compilerschalter 
zu kennen, ist das nur Rumgerate.

state und count sind Variablen? Wie definiert, deklariert?

Die Anzeige des Debuggers kann dich verwirren, siehe auch 
Compilerfehler und

http://sourceware.org/gdb/current/onlinedocs/gdb/O...

Autor: Ben (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, der c Code ist vielleicht echt ein bisschen zu kurz.
Ich schreibs nochmal ausführlicher und poste es dann.

Autor: Ben (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So, hab mal alles (für die Fehlersuche) unnötige rausgeschmissen. Siehe 
Anhang.
Des weiteren fehlen die LCD routinen, aber das sind die bekannten 
"AVR-GCC-Tutorial/LCD-Ansteuerung"

Nochmal eine kurze Fehlerbeschreibung:
Eigentlich dürfte die while Schleife
      if(stateSemicolon<5){
        while(1){
          cli();
          lcd_setcursor(0 ,1 );
          lcd_string("Fehler");
          }
nie erreicht werden,
da direkt davor folgender Ausdruck steht:
    else if(stateSemicolon>4 && stateSemicolon<10 && counterMain==0){

Von der RS232 Schnittstelle werden permanent Nachrichten mit je 150 
Zahlen getrennt durch ';' empfangen.
Zu Beginn jeder Nachricht wird ein '?' gesendet, an dem dann der 
Nachrichtenbeginn erkannt wird.

Zum testen sende ich dem yC 30-40 Nachrichten mit je 150 Zahlen mit 
einer Geschwindigkeit von 57600Baud. Der Fehler tritt manchmal sehr 
schnell auf (geschätzt: nach einigen wenigen Nachrichten) manchmal aber 
auch erst sehr spät (irgendwann nach der 20. bis 30. Nachricht oder noch 
später).

Die Frage war, wie es möglich ist, dass das Programm in die while 
Schleife läuft. stateSemicolon zählt nach oben.

Viele Grüße
Ben

Autor: Torsten K. (ago)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du veränderst stateSemicolon in der Interrupt-routine:

ISR(USART_RX_vect)
...
  if(nextChar=='?'){
    stateSemicolon=1;


Wenn nun also die ISR genau innerhalb von
"else if(stateSemicolon>4" ... und "if(stateSemicolon<5){" ein 
Fragezeichen empfängt, dann hast du Dein Problem :-)

Im Übrigen wird deine Routine ganz ganz ganz allergisch auf 
übertragungsfehler oder manipulierte Eingaben reagieren...

Hier fehlt eindeutig eine Synchronisation zwischen ISR und main():

Ich würde folgendes empfehlen:

zusätzliche Variable deklarieren:

uint8_t stateTemp;

und in main():

stateTemp = stateSemicolon;
while (1)
   while (stateTemp == stateSemicolon) { /* do nothing */};
...

Autor: Ben (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Torsten,

vielen Dank für die Antwort.

Die Abfrage
"if(stateSemicolon<5){"
hab ich nur zum Testen eingefügt. Die fliegt wieder raus wenn das oben 
genannte Problem gelöst ist.

Wenn man mal davon ausgeht das ich jetzt im Testbetrieb nur fehlerfreie 
Übertragungen habe (konnte zum Beispiel bei den übertragenen Zahlen noch 
keinen Fehler feststellen) dann sollte die Variable "stateSemicolon" nur 
nach oben zählen und somit sollte die while Schleife nie erreicht 
werden.

Zusätzlich ist mir aufgefallen, dass wenn ich die else if:
else if(stateSemicolon>4 && stateSemicolon<10 && counterMain==0)
umstelle nach
else if(stateSemicolon<10 && counterMain==0 && stateSemicolon>4)
tritt der Fehler nicht auf, sprich die while Schleife wird nie erreicht

>Hier fehlt eindeutig eine Synchronisation zwischen ISR und main():
Ja, hört sich sinnvoll an, dass werd ich gleich mal einbauen.

>Im Übrigen wird deine Routine ganz ganz ganz allergisch auf
>übertragungsfehler oder manipulierte Eingaben reagieren...
Ich weis da liegt noch einiges an Arbeit vor mir :-(

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.