strcmp() gibt immer "true" zurück

OP #3254464
Lesenswert?

Hallo Leute, folgendes Problem.

Ich nutze einen ATMega8 welchen ich via USART einen Befehl sende.
Naheliegend ist also eine IF Anweisung in Verbindung mit strcmp() 
nachdem der Befehl komplett empfangen wurde.

Interessanterweise scheint strcmp() immer true auszuspucken.

Bei folgendem CodeBeispiel werden beide Ausgänge (OUT_OPEN, OUT_CLOSE) 
angesteuert egal welchen String ich ihm schicke.

Kann mir das jmd erklären ?
1
#define uart_buffer_size 32
2
volatile uint8_t usart_RX_Complete = 0;            // Flag, String komplett empfangen
3
volatile uint8_t usart_TX_Complete = 1;            // Flag, String komplett gesendet
4
char usart_RX_buffer[USART_BUFFER_SIZE];      // Empfangspuffer
5
char usart_TX_buffer[USART_BUFFER_SIZE];      // Sendepuffer
6

7
//Hilfsmethoden
8
void initUSART();
9
void sendString(char* string);
10

11
//Hauptmethode
12
int main(void)
13
{
14
  //I/O-Ebene Konfigurieren
15
  DDRB &= ~((1<<IN_CLOSED) | (1<<IN_OPENED));
16
  PORTB |= (1<<IN_CLOSED) | (1<<IN_OPENED);
17
   
18
  DDRC |= (1<<OUT_STATUS_LED) | (1<<OUT_OPEN) | (1<<OUT_CLOSE);
19
  
20
  
21
  initUSART();  //USART initalisieren
22
  sei();      //Globale Interrupts zulassen
23

24
  //Hauptschleife  
25
  while(1){
26
    //PORTC &= ~((1<<OUT_CLOSE) | (1<<OUT_OPEN));
27
    PORTC |= (1<<OUT_STATUS_LED);
28
    _delay_ms(1000);
29
    PORTC &= ~(1<<OUT_STATUS_LED);
30
    _delay_ms(1000);
31
    
32
    if (usart_RX_Complete == 1){
33
/* Hier werden beide IF-Anweisungen ausgeführt, egal was im usart_RX_buffer steht */
34
      if (strcmp(usart_RX_buffer, "Test")){
35
        PORTC |= (1<<OUT_OPEN);
36
      }
37
      if (strcmp(usart_RX_buffer, "Error")){
38
        PORTC |= (1<<OUT_CLOSE);
39
      }
40
      usart_RX_Complete = 0;
41
    }
Gast #3254477
Lesenswert?

strcmp() gibt 0 zurück wenn die Strings gleich sind, einen Wert größer 0 
wenn das erste nicht-gleiche Zeichen im ersten String einen höheren Wert 
hat und einen Wert kleiner eins im umgekehrten Fall.
OP #3254481
Lesenswert?

foo schrieb:
> strcmp() gibt 0 zurück wenn die Strings gleich sind, einen Wert größer 0
> wenn das erste nicht-gleiche Zeichen im ersten String einen höheren Wert
> hat und einen Wert kleiner eins im umgekehrten Fall.

Upps ja stimmt ^^das erklärte dann wohl ^^ haha ;) So simpel kanns sein 
^^

Vielen dank


Manchmal sieht man den Wald vor lauter Bäumen nicht ^^
OP #3254562
Lesenswert?

Wobei jetzt eher interessant wäre wieso ich nicht auf 0 komme.

Ich sende ihm Exakt den passenden String und trotzdem gibt strcmp() 
nicht 0 raus.
Fällt jmd etwas auf ?

Hier mal der ganze code:
1
/*
2
 * FerRemote.c
3
 *
4
 * Version: 0.1 
5
 *
6
 * Created: 25.07.2013 01:37:51
7
 *  Author: iLem0n
8
 */ 
9

10
#include <avr/io.h>
11
#include <avr/interrupt.h>
12
#include <util/delay.h>
13
#include <string.h>
14

15
#define USART_BUFFER_SIZE 32
16
#define BAUD 9600UL
17

18
//Baudrate und Taktfrequenz prüfen
19
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
20
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))
21
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)
22

23
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
24
#error Systematischer Fehler der Baudrate größer 1% und damit zu hoch!
25
#endif
26

27
//Ein-/Ausgänge
28
#define IN_OPENED PB0
29
#define IN_CLOSED PB1
30

31
#define OUT_OPEN PC0
32
#define OUT_CLOSE PC1
33
#define OUT_STATUS_LED PC2
34

35
//Globale Variablen
36
#define uart_buffer_size 32
37
volatile uint8_t usart_RX_Complete = 0;            // Flag, String komplett empfangen
38
volatile uint8_t usart_TX_Complete = 1;            // Flag, String komplett gesendet
39
char usart_RX_buffer[USART_BUFFER_SIZE];      // Empfangspuffer
40
char usart_TX_buffer[USART_BUFFER_SIZE];      // Sendepuffer
41

42
//Hilfsmethoden
43
void initUSART();
44
void sendString(char* string);
45

46
//Hauptmethode
47
int main(void)
48
{
49
  //I/O-Ebene Konfigurieren
50
  DDRB &= ~((1<<IN_CLOSED) | (1<<IN_OPENED));
51
  PORTB |= (1<<IN_CLOSED) | (1<<IN_OPENED);
52
   
53
  DDRC |= (1<<OUT_STATUS_LED) | (1<<OUT_OPEN) | (1<<OUT_CLOSE);
54
  
55
  
56
  initUSART();  //USART initalisieren
57
  sei();      //Globale Interrupts zulassen
58

59
  //Hauptschleife  
60
  while(1){
61
    /*
62
    PORTC &= ~((1<<OUT_CLOSE) | (1<<OUT_OPEN));
63
    PORTC |= (1<<OUT_STATUS_LED);
64
    _delay_ms(1000);
65
    PORTC &= ~(1<<OUT_STATUS_LED);
66
    _delay_ms(1000);
67
    */
68
    
69
    if (usart_RX_Complete == 1){
70
      sendString(usart_RX_buffer);
71
      
72
      if (strcmp(usart_RX_buffer, "Test\r") == 0){
73
        PORTC |= (1<<OUT_STATUS_LED);
74
      }
75
      if (strcmp(usart_RX_buffer, "Test\0") == 0){
76
        PORTC |= (1<<OUT_OPEN);
77
      }
78
      if (strcmp(usart_RX_buffer, "Test\n") == 0){
79
        PORTC |= (1<<OUT_CLOSE);
80
      }
81
      
82
     
83
      /*
84
      sendString(usart_RX_buffer);
85
      if (strcmp(usart_RX_buffer,"OpenCage")){
86
        while ( PINB & (1<<IN_OPENED)){
87
          PORTC |= (1<<OUT_OPEN);
88
        }
89
        PORTC &= ~(1<<OUT_OPEN);
90
        sendString("Cage_Opened"); 
91
      }
92
      
93
      if (strcmp(usart_RX_buffer, "CloseCage")){
94
        while ( PINB & (1<<IN_CLOSED)){
95
          PORTC &= ~(1<<OUT_OPEN);
96
          PORTC |= (1<<OUT_CLOSE);
97
        }
98
        PORTC &= ~(1<<OUT_CLOSE);
99
        sendString("Cage_Closed");
100
      }
101
      */
102
      usart_RX_Complete = 0;
103
    }
104
  }
105
}
106

107
//###### USART #####
108
void initUSART(){
109
  UBRRH = (unsigned char)(UBRR_VAL>>8);
110
  UBRRL = (unsigned char) UBRR_VAL;
111
  
112
  UCSRB = (1<<RXEN) | (1<<TXEN) | (1<<RXCIE);    //RXEN(Empfang), TXEN(Senden), RXCIE(Empfang komplett Interrupt),
113
  UCSRC = (1<<URSEL) | (3<<UCSZ0);  //1 Stop Bit(s), 8-bit
114
}
115

116
//##### Senden #####
117
void sendString(char* string){
118
  if (usart_TX_Complete == 1){
119
    strcpy(usart_TX_buffer, string);  //String in Sendebuffer laden 
120
    usart_TX_Complete = 0;        //Flag zurücksetzen 
121
    UCSRB |= (1<<UDRIE);        //Senden Interrupt erlauben
122
  }
123
}
124

125
//###### Interrupts #####
126
ISR(USART_RXC_vect) {
127
  //Init
128
  static uint8_t usart_RX_cnt; 
129
  char data;
130
  
131
  data = UDR;                        //Zeichen aus Empfangsregister laden
132
  
133
  if (!usart_RX_Complete) {                //Wenn Empfangen nicht abgeschlossen
134
    if (data=='\r') {                  //Wenn CarriageReturn
135
      usart_RX_buffer[usart_RX_cnt]="\0";        //String terminieren
136
      usart_RX_Complete=1;              //"Empfang komplett"-Flag setzten  
137
      usart_RX_cnt=0;                  //Empfangszähler rücksetzen 
138
    }else if (usart_RX_cnt<(USART_BUFFER_SIZE-1)) {    //Bufferüberlauf verhindern
139
      usart_RX_buffer[usart_RX_cnt]=data;        //Zeichen in Empfangsbuffer schreiben
140
      usart_RX_cnt++;                  //hochzählen
141
    }
142
  }
143
}
144

145
ISR(USART_UDRE_vect) {
146
  //Init
147
  static char* usart_TX_pointer = usart_TX_buffer;  //Pointer auf Sendebuffer
148
  char data;
149

150
  data = *usart_TX_pointer++;              //Zähler im Sendebuffer um 1+ verschieben 
151
  
152
  if (data=="\0") {                  //Wenn terminiert,
153
    UCSRB &= ~(1<<UDRIE);              //Interrupt verbieten
154
    usart_TX_pointer = usart_TX_buffer;        //Pointer zurücksetzen
155
    usart_TX_Complete = 1;              //"Senden komplett"-Flag setzen 
156
  }else UDR = data;                  //Wenn nicht termniniert Zeichen senden
157
}
#3254565
Lesenswert?

Peter C. Glade schrieb:
> Wobei jetzt eher interessant wäre wieso ich nicht auf 0 komme.

Vermutung: Dein Terminal-Programm sendet CRLF, da wird keiner deiner 
Tests glücklich.

evtl. str*n*cmp mit Länge 4 verwenden?

Oder gleich richtig parsen, strtok &co...


Edith:
Hab grad erst deine RXC-ISR gesehen.
das \r filterst du da ja schon raus... Aber:


Test\r\n kommt an.
bei \r setzt du usart_RX_cnt auf 0.
\n kommt aber trotzdem hinterher.
Buffer enthält dann also
"\nest\0"


Edith2: das sollte eigentlich dein "complete"-Flag verhindern...
#3254659
Lesenswert?

Ein kleiner Tip, um solchen Dingen auf die Spur zu kommen.

Das hier
1
    if (usart_RX_Complete == 1){
2
      sendString(usart_RX_buffer);

ist schon gut. Den String zurückschicken ist ok.
Aber: Es gibt auch Zeichen im String, wie die berühmten \r oder \n, die 
sieht man dann im Terminal nicht oder nur sehr schwer. Genausowenig wie 
man Leerzeichen (als schlampiger) Mensch nicht sieht.

D.h. es ist eine gute Idee, sich vor dem STring und hinter dem String 
Terminierungszeichen auszugeben!
1
    if (usart_RX_Complete == 1){
2
      sendString("#");
3
      sendString(usart_RX_buffer);
4
      sendString("#");

tippst du jetzt zb
1
Test
im Terminal, dann muss das Echo so aussehen:
1
#Test#

Sieht es so aus
1
#
2
Test#
dann hast du einen Zeilenumbruch am Anfang des Srings. Sieht es so aus
1
#Test
2
#
dann hast du einen Zeilenumbruch am Ende des Strings. Achte auch auf 
eventuelle Leerzeichen. kriegst du als Echo
1
#Test #
dann hat sich ganz offensichtlich ein Leerzeichen an das Ende des 
Strings gemogelt.

Zur Kontrolle ist es auch immer gut, wenn man sich zusätzlich noch die 
Stringlänge mit ausgeben lässt.
1
    if (usart_RX_Complete == 1){
2
      sendInt( strlen(usart_RX_buffer) );
3
      sendString("#");
4
      sendString(usart_RX_buffer);
5
      sendString("#");
denn dann bleiben auch ansonsten komplett 'unsichtbare' Zeichen nicht 
unentdeckt. Steht dann im Terminal
1
5#Test#
dann ist irgendwo ein nicht darstellbares Zeichen im String versteckt.

Hint2: für eine derartige Debug-Ausgabe lohnt es sich, eine eigene 
Funktion zu machen.

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