if (c >= 'A') zulässig?

Gast #3031050
Lesenswert?

Hallo zusammen,

ich bin gerade dabei Daten welche vom Uart kommen zu sortieren, 
Großbuchstaben möchte ich abfangen.
1
.
2
.
3
/*
4
* Get received character from ringbuffer
5
* uart_getc() returns in the lower byte the received character and 
6
* in the higher byte (bitmask) the last receive error
7
* UART_NO_DATA is returned when no data is available.
8
*/
9
unsigned int ch = uart_getc();
10

11
if ((ch&0x00FF) == 'A') ruleTheWorld();
12
//oder
13
if ((ch<<1) == 'A') ruleTheWorld();
14
//oder
15
if ((char)(ch) == 'A') ruleTheWorld();
16
// oder
17
if ((char)(ch) == 65) ruleTheWorld();

All diese Beispiele fangen meine Buchstaben A nicht ab.

Meine Frage an euch ist also: Wie prüft man Character in C korrekt ab?

Lg,
Marc
Persönliche Seite #3031061
Lesenswert?

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:
1
unsigned int ch = 'A';
2

3
if ((ch&0x00FF) == 'A') ruleTheWorld();
4
//oder
5
if ((char)(ch) == 'A') ruleTheWorld();
6
// oder
7
if ((char)(ch) == 65) ruleTheWorld();
#3031069
Lesenswert?

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
Gast #3031114
Lesenswert?

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
#3031144
Lesenswert?

> 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.
#3031163
Lesenswert?

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:
1
if (ch == 'A') ruleTheWorld();
Gast #3031191
Lesenswert?

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
#3031211
Lesenswert?

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.
Gast #3031360
Lesenswert?

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
void processUartData(char c){
2
  
3
  static char string[6];
4
  static uint8_t i=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( (unsigned char)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
#3031475
Lesenswert?

Außerdem fehlt der Check, ob überhaupt Daten empfangen worden sind:
1
uartRX = uart_getc();
2
if ((uartRX & 0xFF00) == 0) {
3
  processUartData(uartRX);
4
}

Und uartRX hat an der Stelle nichts zu suchen:
1
default: uart_putc( (unsigned char)uartRX );
Da gehört hin:
1
default: uart_putc(c);
Gast #3031543
Lesenswert?

Danke für euer Feedback.
Die Angeführten Fehler habe ich gleich ausgebessert und habe jetzt 
folgende Implementation:
1
void processUartData(char c){
2
  
3
  static char string[6];
4
  static uint8_t i=0;
5
  
6
  if(isupper(c)){  // process only upper case characters
7
      
8
    if (i<5){
9
      string[i]=c;
10
      i++;
11
      uart_puts("if works\n");
12
    }else{
13
      if (strcmp(string, "VER") == 0)
14
      {
15
        uart_puts("Version 1\n");
16
      }
17
      uart_puts("else works\n");
18
      i = 0;
19
      memset(string, 0, sizeof(string));
20
    }
21
    
22
  }else{
23
    switch (c)
24
    {
25
      case 'a': uart_puts("Hello World\n"); break;
26
      default: uart_putc(c);
27
    }
28
  }  
29
}  
30
int main(void)
31
{  
32
  io_init();
33
  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
34
  sei();
35
  while(1)
36
  {
37
    /*
38
         * Get received character from ringbuffer
39
         * 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
#3031562
Lesenswert?

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".
Gast #3031670
Lesenswert?

Danke, jetzt geht es endgültig!!!
Ich bin glücklich :-)
1
  static char string[4];
2
  static uint8_t i=0;
3
  
4
  if(isupper(c)){  // process only upper case characters
5
      
6
    if (i<4){
7
      string[i]=c;
8
      string[i+1]='\0';
9
      i++;
10
      
11
      if (strcmp(string, "VER") == 0)
12
      {
13
        uart_puts("Version 1\n");
14
      }
15
      
16
    }else{
17
      i = 0;
18
      memset(string, 0, sizeof(string));
19
    }
20
    
21
  }else{
22
}

Ihr hattet alle recht.

Schönen Abend noch,
Marc
#3031684
Lesenswert?

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 :-)
Gast #3031876
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren