Forum: Mikrocontroller und Digitale Elektronik Sind Sie sicher Abfrage, Usart, Atmega32


von Jürgen G (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich brauch mal eure Hilfe.
Ich möchte über einen Befehl der von der seriellen Schnittstelle (Putty) 
kommt, einige Strings leeren. Ausgabe auf das Terminal funktioniert. 
(Siehe Bild)
Mein Problem ist jetzt bei Punkt 2.
Drücke ich y oder n wird einfach nur der Buchstabe angezeigt.

Wo liegt mein Fehler?

Verzeiht mir bitte mein Programmierstil. Bin noch in der Lernphase.

Danke für eure Hilfe.

von chbalnuweit (Gast)


Lesenswert?

Ich kann in deiner main nicht erkennen, wo du "uart_string" 
herbekommst...

von chbalnuweit (Gast)


Lesenswert?

Da es scheinbar in der ISR ausgelesen wird, sollte char uart_string 
besser auch volatile sein!

von Jürgen G (Gast)


Lesenswert?

Ok, habs geändert.
Sieht jetzt so aus:
1
volatile uint8_t uart_str_complete=0; 
2
volatile uint8_t uart_str_count=0;
3
volatile char uart_string[10];

Wie muss ich denn folgenden Code ändern das es funktioniert?
1
  if (strcmp (uart_string, "2" ) == 0)
2
      {
3
        uart_string[0] = '\0';
4
      uart_schreibe_string("\n\rSind Sie sicher?\(y\/n\)");
5
      
6
      while( uart_string[1] != '\0');
7
        
8
        if (strcmp (uart_string, "y" )==0)
9
        {
10
          uart_string[0] = '\0';
11
          uart_schreibe_string("Daten geloescht");
12
        }
13
        if (strcmp (uart_string, "n" )==0)
14
          {
15
          uart_string[0] = '\0';
16
          uart_schreibe_string("Hauptmenue");
17
        }
18
      }

von chbalnuweit (Gast)


Lesenswert?

Hast du mal mit einem Minimalbeispiel probiert, ob das Empfangen des 
Strings überhaupt richtig funktioniert?

von chbalnuweit (Gast)


Lesenswert?

1
oid uart_gets( char* Buffer, uint8_t MaxLen ) 
2
{ 
3
  uint8_t NextChar; 
4
  uint8_t StringLen = 0; 
5
  NextChar = uart_getc();   // Warte auf und empfange das nächste Zeichen
6
                // Sammle solange Zeichen, bis:
7
                // * entweder das String Ende Zeichen kam
8
                // * oder das aufnehmende Array voll ist
9
  while( NextChar != '\n') 
10
  {   
11
    *Buffer++ = NextChar; 
12
    StringLen++; 
13
    NextChar = uart_getc(); 
14
  } 
15
        // Noch ein '\0' anhängen um einen Standard
16
        // C-String daraus zu machen
17
  *Buffer = '\0'; 
18
}
 *Buffer = '\0'; <-- Hier überschreibst du das letzte Zeichen mit '\0', 
in deinem Falle vermutlich dein "y" , weshalb deine uart_string immer 
leer ist.

von Jürgen G (Gast)


Lesenswert?

hab gerade folgendes geändert:
1
if (strcmp (uart_string, "ok" ) == 0)// <-----
2
      {
3
        uart_string[0] = '\0';
4
      uart_schreibe_string("\n\rSind Sie sicher?\(y\/n\)");
Jetzt muss ich ok eingeben das die Frage kommt ob ich sicher bin.
Heist also er speichert den String.

von chbalnuweit (Gast)


Lesenswert?

Okay gut, meine Vermutung war auch Unsinn, da da weiter oben ja 
"*Buffer++ = ..." ausgeführt wird, was ein post-inkrement des Pointers 
bedeutet und somit später auch nichts überschrieben wird.
Funktioniert generell das mehrfache Empfangen von Strings?
Versuch mal ein Echo-Programm, sodass der MC immer das auf die Konsole 
zurückgibt, was du eingeben hast. Vielleicht hilft dir das, deinem 
Fehler auf die Spur zu kommen.

von Jürgen G (Gast)


Lesenswert?

Erledigt.
Sobald ich die Entertaste drücke, gibt er genau das aus was ich 
eingegeben habe. Es scheint also, dass er die uart_string richtig 
beschreibt.

Mit dieser while-Schleife möchte ich ja auf eine Antwort des Benutzer 
warten.
1
while( uart_string[1] != '\0');
Also quasie auf ein y oder ein n.
Ist die Abfrage richtig?

von chbalnuweit (Gast)


Lesenswert?

Jürgen G schrieb:
> Sobald ich die Entertaste drücke,
...

von Jürgen G (Gast)


Lesenswert?

???

von chbalnuweit (Gast)


Lesenswert?

Ich bin davon ausgegangen, dass du die Entertaste gedrückt hast, da du 
es so programmiert hast, dass man sie drücken muss.
Wenn du "ok" oder "2" eingetippt hast, wirst du ja wohl auch die 
Entertaste gedrückt haben, oder?

von chbalnuweit (Gast)


Lesenswert?

Sorry, ich glaube wir haben aneinander vorbei geredet:
Ich dachte dein Problem hat sich erledigt, weil du nach dem "y" nicht 
"Enter" gedrückt hast. Aber scheinbar bezog sich dein "Erledigt" auf die 
Idee mit dem Echo-Programm ;-)

Wenn du nur ein Zeichen vom Benutzer erwartest, wieso nimmst du nicht 
einfach die uart_getc() Funktion?
1
while(uart_getc() != "y"){}    // tue nichts solange kein "y"
2
uart_puts("y wurde gedrückt")  // danach sende string zurück

von Jürgen G (Gast)


Lesenswert?

ja, da haben wir an einander vorbei geschrieben.

Dein Vorschlag hat nicht funktioniert.
1
if (strcmp (uart_string, "2" ) == 0)
2
      {
3
        uart_string[0] = '\0';
4
      uart_schreibe_string("\n\rSind Sie sicher?\(y/n)");
5
      
6
      while(uart_getc() != "y"){}
7
        
8
        //if (strcmp (uart_string, "y" )==0)
9
        //{
10
          uart_string[0] = '\0';
11
          uart_schreibe_string("Daten geloescht");
12
        //}
13
        //if (strcmp (uart_string, "n" )==0)
14
          //{
15
        //  uart_string[0] = '\0';
16
        //  uart_schreibe_string("Hauptmenue");
17
        //}
18
      }

Mit diesem code müßte ich doch eigentlich beim Drücken des y, 'Daten 
gelöscht' als Rückmeldung erhalten.
Macht es aber nicht.

Zwischen durch auch mal ein Dankeschön für deine Mühe.

von chbalnuweit (Gast)


Lesenswert?

Ich hätte jetzt erwartet, dass das funktioniert ;) Einen Fehler kann ich 
jetzt nicht erkennen. Ist das wirklich das ganze Programm oder gibt es 
da noch mehr?

von Jürgen G (Gast)


Angehängte Dateien:

Lesenswert?

Es gibt nur noch eine Datei wo die Funktionen für die Ausgabe auf die 
RS232 drin stehen. Hab ich angehängt. Aber das funktioniert ja.
Sonnst würde er mir die Frage ja nicht ausgeben.

Kann ich nicht irgendwie die uart_string sollange abfragen bis da was 
neues drin steht?

Geh jetzt erst mal gefrustet ins Bett:-(
Gute Nacht.

von chbalnuweit (Gast)


Lesenswert?

1
  if (strcmp (uart_string, "2" ) == 0)
2
      {
3
        uart_string[0] = '\0';
4
      uart_schreibe_string("\n\rSind Sie sicher?\(y\/n\)");
5
6
      // Versuche hier mal "uart_string" an die Konsole auszugeben
7
      // damit du sehen kannst, was überhaupt drin steht.
8
      
9
      while( uart_string[1] != '\0');
10
        
11
        if (strcmp (uart_string, "y" )==0)
12
        {
13
          uart_string[0] = '\0';
14
          uart_schreibe_string("Daten geloescht");
15
        }
16
        if (strcmp (uart_string, "n" )==0)
17
          {
18
          uart_string[0] = '\0';
19
          uart_schreibe_string("Hauptmenue");
20
        }
21
      }

Hast du LEDs oder ein Oszi oder so angeschlossen, was du zum Debuggen 
nehmen könntest?
Eigentlich kann es ja nur so sein, dass er hier
1
 while( uart_string[1] != '\0');
hängen bleibt.
Du könntest versuchen, einen delay einzubauen und einen Pin in der 
Schleife zu toggeln. Dann kannst du das mit LED oder Oszi sichtbar 
machen.
Z.B. so:
1
 while( uart_string[1] != '\0')
2
 {
3
   _delay_ms(200)
4
   PORTA ^= (1<<PA0) 
5
 }

von Mike A. (Gast)


Lesenswert?

Jürgen G schrieb:
> Also quasie auf ein y oder ein n.

Wehe der Benutzer drückt "Y" oder "N"

von Jürgen G (Gast)


Angehängte Dateien:

Lesenswert?

So, hat etwas gedauert.

chbalnuweit schrieb:
> // Versuche hier mal "uart_string" an die Konsole auszugeben
>       // damit du sehen kannst, was überhaupt drin steht.

Das ist meine Antwort drauf:
1
if (strcmp (uart_string, "2" ) == 0)
2
      {
3
      uart_schreibe_string(uart_string);
4
      uart_string[0] = '\0';
5
      uart_schreibe_string(uart_string);
6
      /*
7
      while( uart_string[1] != '\0')
8
      {
9
           _delay_ms(200);
10
           PORTC ^= (1<<PC7);
11
       }
12
        
13
        
14
          if (strcmp (uart_string, "y" )==0)
15
          {
16
            uart_string[0] = '\0';
17
              uart_schreibe_string("Daten geloescht");
18
          }
19
          if (strcmp (uart_string, "n" )==0)
20
            {
21
              uart_string[0] = '\0';
22
              uart_schreibe_string("Hauptmenue");
23
          }*/
24
        }

Siehe Bild

Das ist der nächste Versuch:
1
if (strcmp (uart_string, "2" ) == 0)
2
      {
3
      uart_string[0] = '\0';
4
      uart_schreibe_string("\n\rSind Sie sicher?");
5
6
      while( uart_string[1] != '\0')
7
      {
8
           _delay_ms(200);
9
           PORTC ^= (1<<PC7);
10
       }
11
        
12
        
13
          if (strcmp (uart_string, "y" )==0)
14
          {
15
            uart_string[0] = '\0';
16
              uart_schreibe_string("Daten geloescht");
17
          }
18
          if (strcmp (uart_string, "n" )==0)
19
            {
20
              uart_string[0] = '\0';
21
              uart_schreibe_string("Hauptmenue");
22
          }
23
        }
Led blinkt nicht.
Soll heisen, er bleibt nicht hängen und fragt somit auch nicht die 
Tasten ab. Was tun?

Danke für die Hilfe!

von chbalnuweit (Gast)


Lesenswert?

Hast du auch vorher PC7 auf PortC  mit
1
DDRC = (1<<PC7) als Ausgang definiert?

Versuch weiter mit der LED zu debuggen.

Verschiebe das toggeln der LED zum Beispiel hier hin:
1
 if (strcmp (uart_string, "y" )==0)
2
          {
3
            PORTC ^= (1<<PC7);
4
            uart_string[0] = '\0';
5
            uart_schreibe_string("Daten geloescht");
6
          }

Du musst erstmal herausfinden, wo etwas schief läuft. Dann kann man 
sehen, was ggf. schief läuft.

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

du musst blos auf die Abfrage auf "Sind sie sicher?"  mit j/n anstelle 
y/n prüfen, dann funktioniert alles  .... oder soll y = "yoh, man" 
bedeuten?

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Du solltest nicht einfach Code übernehmen, ohne ihn wenigstens 
rudimentär zu verstehen.

Deine ganzen Abfragen kranken alle an einem Punkt:

Der erste Anlaufpunkt, die erste Abfrage die du machen musst, ist 
diejenige ob uart_str_complete den Wert 1 hat. Denn DAS ist das Signal, 
mit der dir die ISR signalisiert "Huhu! Ich hab eine komplette Zeile. 
Bitte auswerten!"

Und das hier
1
ISR(USART_RXC_vect) 
2
{ 
3
  unsigned char buffer; 
4
  buffer = UDR; 
5
  if( uart_str_complete==0 ) 
6
  { 
7
    if(buffer!='\n'&& buffer!='\r') 
8
    { 
9
      uart_string[uart_str_count]=buffer;
10
      uart_putc(uart_string[uart_str_count]); 
11
      uart_str_count++; 
12
    }
13
    else
14
    { 
15
      uart_string[uart_str_count]='\0'; 
16
      uart_str_count=0; 
17
      uart_str_complete=1;
18
      uart_schreibe_string("\n\r");
19
    } 
20
  } 
21
22
                           // *******************
23
  uart_str_complete=0;     // <--------- das hier
24
                           // *******************
25
26
}
(das Setzen von uart_str_complete auf 0 am Ende) gehört da überhaupt 
nicht rein. Entweder hat derjenige, bei dem du abgeschrieben hast, 
nichts verstanden oder du selbst hast das verbockt.

Du selbst setzt dann in deinem Hauptprogramm usart_str_complete wieder 
auf 0, und zwar NACHDEM du den String der reingekommen ist augewertet 
hast. So wie das jetzt programmiert ist, ist nämlich uart_str_complete 
völlig nutzlos. Da hätte man sich die Variable auch sparen können. Nur: 
Die Variable ist vital für das funktionieren des ganzen! Deine ganzen 
Abfragen, ob irgend ein Zeichen in deinem Array '\0' wird, um daran das 
Ende einer Eingabe zu erkennen, ist völliger Humbug.

Also: 0 Setzen aus der ISR raus. Dafür die Abfrage in main, ob die ISR 
anzeigt, dass ein String komplett ist und nach der Auswertung des 
Strings, wenn die UART wieder scharf gestellt wird, die Variable auf 0 
setzen.

Dafür schreibst du:
1
....
2
  uart_schreibe_string("Menue:\n\r"
3
                       " 1.\)Daten lesen\n\r"
4
                       " 2.\)Daten loeschen\n\r"
5
                       " 3.\)Datum einstellen\n\r"
6
                       " 4.\)Uhr einstellen");
7
8
  while(1) 
9
  { 
10
    // gibt es eine fertige Eingabe über die UART?
11
    if (uart_str_complete != 0) {
12
13
      // Ja, es gibt eine. Was war es?
14
15
      if (strcmp (uart_string, "1") == 0)
16
      {
17
        uart_schreibe_string("\n\rFolgende Daten sind gespeichert");
18
        uart_schreibe_string("\n\r");
19
      }
20
21
      else if (strcmp (uart_string, "2" ) == 0)
22
      {
23
        uart_schreibe_string("\n\rSind Sie sicher?\(y\/n\)");
24
25
        // die UART wieder zum Empfang freigeben
26
        uart_str_complete = 0;
27
        // warte auf den Benutzer. Wenn er Return drückt, dann
28
        // geht uart_str_complete auf 1
29
        while( uart_str_complete == 0 )
30
          ;
31
32
        // was war die Benutzereingabe?        
33
        if (strcmp (uart_string, "y" ) == 0 ||
34
            strcmp (uart_string, "Y" ) == 0 )
35
        {
36
          uart_schreibe_string("Daten geloescht");
37
        }
38
39
        // wenn die Eingabe nicht 'y' war, dann nehmen wir
40
        // automatisch 'n' an. Denn was soll passieren, wenn der
41
        // Benutzer zb 'o' drueckt?
42
        else
43
          uart_schreibe_string("Hauptmenue");
44
        }
45
      }
46
47
      // was auch immer die Benutzereingabe war. Jetzt ist sie
48
      // fertig abgehandelt und die UART kann wieder freigeschaltet werden
49
      // so dass sie die naechsten Zeichen sammelt
50
      uart_str_complete = 0;
51
    }
52
53
  } 
54
}


Wenn du mit er Eingabe per Interrupt und wie man die auswertet nicht 
klar kommst, warum verwendest du die überhaupt? In deinem Programm 
bringt dir die genau gar nichts, weil du sowieso dauernd auf einen 
Benutzer wartest. Da könntest du dir diesen ganzen Hack-Mack auch sparen 
und gleich ohne Interrupts und dafür mit der Funktion uart_gets 
arbeiten. Das wäre in deinem Fall viel einfacher. Du rufst uart_gets auf 
und wenn die Funktion einen String (= eine Zeile) gesammelt hat, dann 
kehrt sie zurück.

> Wenn du nur ein Zeichen vom Benutzer erwartest, wieso nimmst
> du nicht einfach die uart_getc() Funktion?

weil er einen Empfangs Interrupt im Spiel hat. entweder uart_getc und 
uart_gets oder eine Abhandlung über den Interrupt. Aber nicht beides 
bunt gemischt. Das funktioniert nämlich nicht.

> while(uart_getc() != "y"){}    // tue nichts solange kein "y"

Oh Mann. Da berät auch wieder ein Einäugiger einen Blinden.
Du kennst den Unterschied zwischen einem String und einem Character?

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Das einzige was jetzt noch sein kann, das ist, dass dein Terminal beim 
Drücken der Return Taste sowohl ein Carriage Return als auch ein Line 
Feed schickt (also beides: \r UND \n). Im Sinne der Einfachheit 
kontrollier das und stelle dein Terminal so ein, dass es NUR ein 
LineFeed (\n) schickt. Denn das ausfiltern aller Möglichkeiten, die hier 
möglich sind, scheint nach ein paar Schuhnummern zu schwer für dich zu 
sein.

von Thomas K. (thomas_k39)


Lesenswert?

Jürgen G schrieb:
1
 if (strcmp (uart_string, "2" ) == 0)
2
       {
3
       uart_string[0] = '\0';
4
       uart_schreibe_string("\n\rSind Sie sicher?");
5
 
6
       while( uart_string[1] != '\0')
7
       {
8
            _delay_ms(200);
9
            PORTC ^= (1<<PC7);
10
        }

Die while-Schleife kann so nicht funktionieren!

Der strcmp in der ersten Zeile prüft auf
1
uart_string[0] == '2' && uart_string[1] == '\0'

Das heisst, wenn der Benutzer nicht mindestens zwei Zeichen eingegeben 
hat, bevor der Code zum
1
while( uart_string[1] != '\0)
 kommt, wird die Schleife einfach übersprungen.

von Jürgen G (Gast)


Lesenswert?

So, hat etwas gedauert.
Es funktioniert jetzt.

Herzlichen Dank!!!

Karl Heinz schrieb:
> Oh Mann. Da berät auch wieder ein Einäugiger einen Blinden.

Wie soll der Blinde sehen, dass der andere Einäugig ist? ;-)

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.