www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik switch Anweisung default Zweig (Kompilerfehler?)


Autor: Matthias R. (matsch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Forum,
ich habe ein Problem mit folgender switch-case Anweisung:
switch (Befehl){
 case 'D' :                      
   uart_puts("ein D\r");
   break;
 case 'R' :                      
   uart_puts("ein R\r");
   break;
 case 'W' :
   uart_puts("ein W\r");
   break;
 case 'P' :                      
   uart_puts("ein P\r");
   break;
 default:
   uart_puts("nop\r");
   break;
}
In 'Befehl' steht ein Zeichen, welches ich über RS232 mit meinem 
ATMega88 empfange. Je nach empfangenem Zeichen wird eine Antwort über 
RS232 an den PC gesendet (mit der UART library von P. Fleury).
Das ganze funktioniert auch sehr gut.

Nun habe ich neu den default-Zweig eingefügt. Wenn jetzt ein ungueltiges 
Zeiche empfangen wird, soll ein 'nop' gesendet werden - funktioniert 
auch.

ABER: Wenn ein gültiges Zeichen empfangen wird (D, R, W oder P) wird 
neben dem zugehörigen Text auch immer noch das 'nop' aus dem default 
Zweig gesendet.
Nach meinem Verständnis soll der default Zweig aber nur durchlaufen 
werden, wenn keine andere Bedingung erfüllt ist, und nicht bei jeder 
richtigen UND falschen Bedingung.

Ist das ein Kompilerfehler oder habe ich einen Fehler zwischen den 
Ohren?
Wie erreiche ich, dass der default Zweig NUR bei ungültigen Zeichen 
durchlaufen wird?

P.S.
Ich verwende avr-gcc (WinAVR 20080610) 4.3.0

Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das sieht eher nach einem Problem in der Datenübertragung aus. Z.b. 
verwendet dein Terminal 9 Bit, statt 8. o.ä. so dass dein µC denkt, es 
würde 2 Zeichen empfangen. setze mal dort an...

Zum debuggen: Einfach mal vor das Switch ein:
char str[8];
sprintf(str, "RX: %02X\n\r", Befehl);
printf(str);

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie sendest du denn die Zeichen an den Controller? Am Terminal das 
Zeichen eigeben und Enter drücken..? --> Zwei Zeichen!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jede Wette du empfängst in Wirklichkeit nicht 1 Zeichen sondern 2. Zb 
ein abschliessendes Return nach dem Buchstaben.

Lass dir doch einfach mal den 'Befehlsbuchstaben' zurückgeben (als 
Zeichen und zusätzlich den ASCII Code in Zahlenform) dann siehst du was 
dein Programm wirklich zu Gesicht bekommt.

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich bin immer wieder erstaunt, das fast alle Kompilerfehler von 
Anfängern gefunden werden...

Oder ist es vielleicht doch einfach nur die Selbstüberschätzung der 
Anfänger, die immer zuerst dem Kompiler die Schuld geben?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus schrieb:
> Oder ist es vielleicht doch einfach nur die Selbstüberschätzung der
> Anfänger, die immer zuerst dem Kompiler die Schuld geben?

Ich unterstelle niemandem in dem Bereich eine böse Absicht.
Es ist einfach der Lernprozess, dass unser vermeintlich gut 
funktionierendes Gehirn ganz schnell den Überblick über vermeintlich 
einfache Abläufe verliert.

Autor: (nein) (ich) (bin) (kein) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
versuche es mit einem lokalen funktionsblock, also {} nach jedem case


quasi case 'a': {//weil hier mehr als ein Befehl kommt}

Autor: (nein) (ich) (bin) (kein) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wenn du ein oszi hast, siehst du, ob zwei zeichen gesendet werden...
ist noch viel wahrscheinlicher, als dass du {} verwenden musst.

Autor: Matthias R. (matsch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich bin immer wieder erstaunt, das fast alle Kompilerfehler von
> Anfängern gefunden werden...
@Klaus
OK, ich bin nicht der Profi, und habe auch nicht wirklich an einen 
Kompilierfehler geglaubt. Die echten Fehler des Kompilers sind bestimmt 
nicht von so einfacher Natur. Darum auch das '?'. Dafür kann ich besser 
Minigolf ;-)

@Sven, K-H.
Richtig, ich sende nicht nur ein Zeichen sondern eine Zeichenkette mit 
abschießendem 'CR' (ist die Ende Kennung). Zusammen bis zu 4 Zeichen 
(das CR mitgezählt.
Die Routine wird eigentlich aber erst aufgerufen, wenn die Ende Kennung 
gefunden wurde (so hofft der Anfänger).
Ich werde eure Tipps mal verfolgen. Danke schon mal. Ist echt gut, dass 
einige von euch hier auf andere Bäume hinweisen, wenn mann den Wald 
nicht mehr sieht.... Wobei ich auch immer für eine spitzfindige 
Bemerkung offen bin.

MfG
Matthias

Autor: Matthias R. (matsch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Jede Wette du empfängst in Wirklichkeit nicht 1 Zeichen sondern 2. Zb
> ein abschliessendes Return nach dem Buchstaben.

Vor der Switch Anweisung kopiere ich mir das erste Zeichen des Strings 
in die Variable 'Befehl':
Befehl  = String[0]; // erstet Zeichen aus dem String holen
Parameter1 = String[1]; // zweites Zeichen aus dem String holen

switch (Befehl){
... siehe oben ...
}

der default Zweig wird aber wie beschrieben durchlaufen.

matsch

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias R. schrieb:

> Ich werde eure Tipps mal verfolgen.

Der Haupttip ist immer:
Spick dein Programm mit Ausgaben. Wenn du nicht weißt, warum eine 
bestimmte Aktion ausgelöst wird, dann mach vor den entscheidenden if 
(oder in deinem Fall switch) eine Ausgabe rein, die dir den 
'Entscheidungsträger' anzeigt.

In deinem Fall hätte sich auch angeboten ...
 default:
   uart_putc("->'");
   uart_putc(Befehl);
   uart_putc("'"); 
   uart_puts("nop\r");
   break;

... damit du nicht nur siehst, dass etwas nicht verarbeitbares in den 
Verteiler gekommen ist, sondern auch noch siehst was das den war.
Bei einer 'Fehlermeldung' ist es immer gut, den Auslöser auch mit 
auszugeben. Die Anzahl der von Micorosoft mit der simplen Fehlermeldung 
in die Verzweiflung getriebenen Programmierer "Eine DLL konnte nicht 
gefunden werden" ist legendär  .... Verdammt - WELCHE?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias R. schrieb:

> der default Zweig wird aber wie beschrieben durchlaufen.

Der ganze switch-case wird dann aber wahrscheinlich in einer 
übergeordneten Schleifenstruktur ein zweites mal aufgerufen.

Mach mal folgendes:
switch (Befehl){
 case 'D' :                      
   uart_puts("ein D\r");
   break;
 case 'R' :                      
   uart_puts("ein R\r");
   break;
 case 'W' :
   uart_puts("ein W\r");
   break;
 case 'P' :                      
   uart_puts("ein P\r");
   break;
 default:
   uart_puts("nop\r");
   break;
}

uart_puts( "Fertig\r" );   // <-

Autor: Matthias R. (matsch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> ... sondern auch noch siehst was das den war.
Danke für den Tipp, den Fehler mit auszugeben.

Die Funktion wurde tatsächlich immer zwei mal aufgerufen. Fehler 
erkannt, gefunden, behoben ... und der Anfänger hat sogar das 'warum' 
verstanden.

Danke
Matsch

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(nein) (ich) (bin) (kein) schrieb:
> versuche es mit einem lokalen funktionsblock, also {} nach jedem case
>
>
> quasi case 'a': {//weil hier mehr als ein Befehl kommt}

So ein Quatsch!

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das mit dem "Kompilerfehler" im Betreff ist schon richtig...

Auf keine andere Weise kriegt man im GCC-Forum so schnell gute und 
fundierte Antworten.
Mit dem Betreff "Wie funktioniert default: in switch" wären nur 
haufenweise Antworten wie "Kauf dir ein C-Buch" gekommen

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.