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.
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.
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?
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?
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
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.
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?
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.
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:
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!
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
unsignedcharbuffer;
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
elseif(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?
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.
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? ;-)