Terra schrieb:> All diese Beispiele fangen meine Buchstaben A nicht ab.
Was heißt für Dich "abfangen"? Aufrufen von "ruleTheWorld"?
Alle Beispiele bis auf eines sind gleichwertig, und alle sollten
funktionieren.
1
if((ch<<1)=='A')ruleTheWorld();
Das ist Quark. Gequirlt, gerührt und geschüttelt.
Probier doch mal das hier:
Terra schrieb:> All diese Beispiele fangen meine Buchstaben A nicht ab.
Müssten sie aber. Dann würde ich mal vermuten, dass in Deinem ch aus
irgendwelchen Gründen einfach kein 'A' drinnen ist.
Terra schrieb:> Meine Frage an euch ist also: Wie prüft man Character in C korrekt ab?
Da gibt es die Funktionen:
isalpha(x) true wenn es ein Buchstabe ist
islower(x) true wenn es ein Kleinbuchstabe ist
isupper(x) true wenn es ein Grossbuchstabe ist
isalnum(x) true wenn es Buchstabe oder Ziffer ist
isdigit(x) true wenn es eine Ziffer ist
isxdigit(x) true wenn es eine Hex Ziffer ist
alles in ctype.h
Ralf G. schrieb:> Rufus Τ. Firefly schrieb:>> Probier doch mal das hier:>> unsigned int ch = 'A';>> Steht das 'A' dann nicht im High-Byte?
Nein. Das ist nichts anderes als:
Ralf G. schrieb:> Steht das 'A' dann nicht im High-Byte?
Richtig. Totaler Käse. Hab' überlegt, ob die zurückgegebenen 16 Bit
vielleicht vertauscht sind, weil der Sender die 'andersrum' im Speicher
ablegt.
Vielen Dank für euer Feedback.
Offenbar gibt es noch irgendwo einen anderen Fehler weil, wie gesagt
ruleTheWorld() nicht aufgerufen wird.
Danke für folgenden Tipp:
isupper(x) true wenn es ein Grossbuchstabe ist
das werde ich gleich probieren. Leider habe ich kein Debuginterface,
sonst wäre das Problem schon gefunden...
Wichtig für mich war euer Feedback, dass mein Code grundsätzlich OK ist
und der Hinweis auf isupper().
DANKE
Ralf G. schrieb:> Hab' überlegt, ob die zurückgegebenen 16 Bit> vielleicht vertauscht sind, weil der Sender die 'andersrum' im Speicher> ablegt.
Liefert denn uart_getc einen 16-Bit-Wert? Das wäre für eine UART sehr
ungewöhnlich.
> Liefert denn uart_getc einen 16-Bit-Wert? Das wäre für eine UART sehr> ungewöhnlich.
Steht zumindest im Kommentar:
1
/*
2
* Get received character from ringbuffer
3
* uart_getc() returns in the lower byte the received character and
4
* in the higher byte (bitmask) the last receive error
5
* UART_NO_DATA is returned when no data is available.
6
*/
UART_NO_DATA ist wahrscheinlich -1, um kompatibel zu EOF aus stdio.h zu
sein. Irgendwie muss man ja kodieren, ob ein neues Zeichen empfangen
wurde oder nicht, wenn uart_getc() nicht blockieren soll.
Rufus Τ. Firefly schrieb:> Liefert denn uart_getc einen 16-Bit-Wert? Das wäre für eine UART sehr> ungewöhnlich.
Ja, bei der Fleury-Lib ist das so. Das obere Byte enthält den
Fehlercode, z.B. wenn kein Zeichen gelesen wurde (UART_NO_DATA). Dieser
Fehlercode sollte nach Aufruf von uart_getc geprüft werden. Das hat der
TO wohl versäumt.
Fabian O. schrieb:> UART_NO_DATA ist wahrscheinlich -1, um kompatibel zu EOF aus stdio.h zu> sein.
Oder auch nicht ...
1
#define UART_NO_DATA 0x0100 /* no receive data available */
Jedenfalls wäre es dann sinnvoll, das obere Byte nicht auszumaskieren.
Denn im Fehlerfall oder bei keinen Daten kann ja alles mögliche im
unteren Byte stehen:
Ja, uart_getc liefert einen 16-bit Wert, genau wie ihr erkannt habt
verwende ich die Fleury-Lib. (Darum habe ich den Kommentar mit Hinweis
auf 16-bit mitkopiert.)
Die Fehlerbehandlung funktioniert, auch das "Echo" der Zeichen
funktioniert, nur das Abfangen von einem String z.B. "VERSION" will
nicht funktionieren.
1
if(ch=='A'){
2
uart_putcs("hello");// Mein Aufruf
3
}else{
4
uart_putc(ch);// Echo
5
}
Wie gesagt das "hello" wird nicht geschickt, das Echo funktioniert.
Ich werde mich noch weiter mit dem Problem beschäftigen.
DANKE
Terra schrieb:> uart_putcs("hello"); // Mein Aufruf> Wie gesagt das "hello" wird nicht geschickt,
Kein Wunder, die Stringsendefunktion heißt uart_puts(...).
Wenn Du das Echo so schreibst, musst Du allerdings vorher das High-Byte
geprüft haben, ob überhaupt etwas empfangen wurde! Sonst sendest Du
ständig etwas.
Die Funktion uart_putcs() gibt es übrigens nicht in der Fleury-Lib ...
Am besten postest Du mal den richtigen Code, dann kann man Dir bestimmt
schnell sagen, wo der Fehler liegt.
Fabian, hast recht, ich werde am besten den gesamten Code posten. (Das
isupper() geht schon :-)
Aufruf:
1
uartRX=uart_getc();
2
processUartData((char)(uartRX&0x00FF));
Funktion:
1
voidprocessUartData(charc){
2
3
staticcharstring[6];
4
staticuint8_ti=0;
5
6
if(isupper(c)){// process only upper case characters
7
8
if(i<5&&c!='\r'){
9
string[i]=c;
10
i++;
11
}else{
12
if(strcmp(&string,"VER")==0)
13
{
14
uart_puts("Version 1\n");
15
}
16
i=0;
17
}
18
19
}else{
20
switch(c)
21
{
22
case'a':uart_puts("Hello World\n");break;
23
default:uart_putc((unsignedchar)uartRX);
24
}
25
}
Inzwischen geht das Erkennen der Großbuchstaben, aber bei der Eingabe
"VER" möchte ich "Version 1" ausgeben.
Das schaffe ich irgendwie nicht.
DANKE,
Marc
Terra schrieb:> if (strcmp(&string, "VER") == 0)> {> uart_puts("Version 1\n");> }
strcmp gibt 0 zurueck wenn gleich
du brauchst auch nicht &string zu schreiben sondern nur string.
Terra schrieb:> if (strcmp(&string, "VER") == 0)
strcmp erwartet 2 C-Strings. Dein char-Array "string" ist aber kein
C-String (Nullterminierung fehlt).
Sebastian W. schrieb:> isupper('\r') ist nicht wahr.
Dann sag mit doch mal bitte den Grossbuchstaben von Carrige Return.
Das darf ja auch nicht wahr sein, ist ja kein Buchstabe.
* uart_getc() returns in the lower byte the received character and
40
* in the higher byte (bitmask) the last receive error
41
* UART_NO_DATA is returned when no data is available.
42
*
43
*/
44
uartRX=uart_getc();
45
if(uartRX&UART_NO_DATA)
46
{
47
/*
48
* no data available from UART
49
*/
50
}
51
else
52
{
53
/*
54
* new data available from UART
55
* check for Frame or Overrun error
56
*/
57
if(uartRX&UART_FRAME_ERROR)
58
{
59
/* Framing Error detected, i.e no stop bit detected */
60
uart_puts_P("UART Frame Error. No stop bit?");
61
}
62
if(uartRX&UART_OVERRUN_ERROR)
63
{
64
/*
65
* Overrun, a character already present in the UART UDR register was
66
* not read by the interrupt handler before the next character arrived,
67
* one or more received characters have been dropped
68
*/
69
uart_puts_P("UART Overrun Error.");
70
}
71
if(uartRX&UART_BUFFER_OVERFLOW)
72
{
73
/*
74
* We are not reading the receive buffer fast enough,
75
* one or more received character have been dropped
76
*/
77
uart_puts_P("Buffer overflow error.");
78
}
79
processUartData((char)(uartRX&0x00FF));
80
}
81
}
82
}
Wenn ich "VER" an den Controller sende bekomme ich als Feedback:
if works
if works
if works
Wenn ich ein zweites Mal "VER" schicke bekomme ich:
if works
if works
else works
Cool, so weit war ich noch nie. Leider noch nicht am Ziel.
Was meint ihr?
Lg,
Marc
Terra schrieb:> Wenn ich "VER" an den Controller sende bekomme ich als Feedback:> if works> if works> if works>> Wenn ich ein zweites Mal "VER" schicke bekomme ich:>> if works> if works> else works
Ja klar. So hast Du es programmiert. Fünf mal "if works" bekommst Du,
weil Deine Abfrage
Terra schrieb:> if (i<5)
genau 5 mal wahr ist. Beim Empfang des zweiten "R" wird diese Bedingung
unwahr und der else-Zweig wird ausgeführt. Es wird also eine Vergleich
zwischen Deinem char-Array "string" mit dem Inhalt "VERVE" und dem
char-Array "VER\0" ausgeführt. Diese beiden Arrays sind ungleich (strcmp
liefert nicht 0). Folglich kommt die Ausgabe "else works".
Patrick Dohmen schrieb:> strcmp benötigt die null-Terminierung vor dem Aufruf!
Die ist vorhanden, denn als statische Variable wird 'string' komplett
mit 0 initialisiert (was natürlich nicht heißt, dass eine explizite
Null-Terminierung im Code nicht sinnvoll wäre).
Meine Meinung:
Die Dinge trennen
* eine Zeile empfangen, wobei Zeile definiert ist als eine Abfolge von
Zeichen, bis zum abschliessenden \r (oder \n)
* ist die Zeile vollständig, dann wird sie ausgewertet, indem sie zb mit
einer Liste von SChlüsselwörtern verglichen wird.
Zum einen erhält man so bessere in sich abgeschlossene Einheiten. Zum
anderen fehlt ja in deinem Programm auch noch eine Möglichkeit, wie zb
ein Benutzer eine Fehleingabe korrigieren kann, in dem er zb mit
Backspace das zuletzt eingegebene Zeichen wieder zurücknimmt. Oder
machst du keine Tippfehler?
Und noch ein kleiner Hinweis.
Es ist nett, wenn du dir "if works" etc. ausgeben lässt. Aber wenn ich
Probleme mit einem Vergleich habe, dann würde ich mir einfach mal den
STring mit dem ich vergleiche ausgeben lassen :-)
Terra schrieb:> Danke, jetzt geht es endgültig!!!
Aber nur zufällig.
> static char string[4];> if (i<4){
d.h. i kann den Wert 3 annehmen
> string[i]=c;> string[i+1]='\0';
Damit greifst du hier auf string[4] zu. string[4] existiert aber nicht.
Karl Heinz, guter Punkt den falschen String auszugeben, macht Sinn :-)
Die Größe des Arrays habe ich auch noch um eines erhöht. Alle Befehle
sollen aus exakt 3 Zeichen bestehen. Das funktioniert schon ganz gut.
DANKE