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


von Ben (Gast)


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:
1
...
2
else if(state>12 && state<17 && count==2)count=3;
3
else if(state>4 && state<10 && count==0)count=1; //Ich denke hier liegt der Fehler
4
5
switch(count){
6
case 3:
7
 //hier wird der gerade per USART empfangene Wert am LCD ausgegeben
8
 count++;
9
 break;
10
case 1:
11
 //hier wird der gerade per USART empfangene Wert am LCD ausgegeben
12
 count++;
13
 break;
14
}
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:
1
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
von Kai S. (zigzeg)


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

von Johann L. (gjlayde) Benutzerseite


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/Optimized-Code.html#Optimized-Code

von Ben (Gast)


Lesenswert?

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

von Ben (Gast)


Angehängte Dateien:

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
1
      if(stateSemicolon<5){
2
        while(1){
3
          cli();
4
          lcd_setcursor(0 ,1 );
5
          lcd_string("Fehler");
6
          }
nie erreicht werden,
da direkt davor folgender Ausdruck steht:
1
    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

von Torsten K. (ago)


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 */};
...

von Ben (Gast)


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:
1
else if(stateSemicolon>4 && stateSemicolon<10 && counterMain==0)
umstelle nach
1
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 :-(

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
Noch kein Account? Hier anmelden.