Probleme mit String

OP #2408421
Lesenswert?

Hallo,

ich habe folgendes Problem. Ich hab die unten angegebene Funktion in 
mein µC geladen. Der Spricht über UART mit einem GSM-Modul. Diese 
Funktion wird aufgerufen, um einen Status des Moduls abzufragen. Doch 
komischerweise, bekomme nichts zurück (sehe ich über die vorletzte Zeile 
"putString(Rueckgabe)".
1
char *Status(char *AT_Befehl, char *Antwort, int TimeOut)
2
{
3
  char *Rueckgabe = NULL;
4
  int i = 0;
5

6
  Puffer_loeschen();              //Puffer löschen
7
  putString(AT_Befehl);            //AT-Befehl senden
8
  waitMs(TimeOut);              //etwas warten
9

10
  while(!(strstr (_buffer, Antwort)))      //falls vorhanden Antwort prüfen
11
  {
12
    waitMs(1000);              //etwas Zeit verbummeln beim warten
13
    
14
    //falls die Zeit überschritten wird, "Error" als Rückgabewert übertragen und
15
    //die Schleife vorzeitig beenden. Sonst kann es zu Endlosschleifen kommen.
16
    if (i>=10)     
17
    {
18
      Rueckgabe = "Error";        //"Error" zurückgeben, falls keine Antwort
19
      goto ende;              
20
    }
21
    i++;
22
  }
23

24
  Rueckgabe = strstr (_buffer, Antwort);    //Wert in Variable schreiben
25
  strcat(Rueckgabe, "\r\n");
26
  ende:                    //Sprungmarke für Vorzeitige Beendung
27
  Puffer_loeschen();              //Puffer löschen
28
  putString(Rueckgabe);            //zu Testzwecken
29
  return Rueckgabe;              //Antwort als Rückgabewert
30
}


Wenn ich testweise die Deklaration z.B. durch
1
char *Rueckgabe = "Hallo";
 ersetzte und die Zeile
1
Rueckgabe = strstr (_buffer, Antwort);
 auskommentiere, dann bekomme ich ein "Hallo" zurück. Ich weiß aber das 
die richtige Antwort beim µC ankommt, 1. beobachte alles über einen HT 
und 2. müsste er mir sonst ein "Error" aus der If-Anweisung senden. Ich 
vermutet, dass das Problem irgendwo in der Zeile
1
Rueckgabe = strstr (_buffer, Antwort);
 liegt. Ich komme aber gerade nicht weiter, hat jemand eine Idee ???

Gruss
#2408472
Lesenswert?

so ganz verstehe ich auch nicht, was es machen soll (weil der Rest vom 
Programm fehlt), aber ich glaube nicht, daß du das hier so machen 
willst:
1
  Rueckgabe = strstr (_buffer, Antwort);    //Wert in Variable schreiben
2
  strcat(Rueckgabe, "\r\n");

_buffer wird ja irgendwie eine globale Variable sein, die von irgendwo 
gefüllt wird (Interrupt? anderer Thread?).

Mit strstr bekommst du einen Zeiger in den Puffer, und mit
strcat() änderst du diesen Puffer!

PS: bist du sicher, daß der Puffer immer nullterminiert ist?
Irgendwann muß er ja mal verlängert werden, und möglicherweise
gleichzeitig suchst du darin (und verlässt dich auf die \0 am Ende).
OP #2408503
Lesenswert?

So ganz habe ich das jetzt nicht verstanden. Hier ist das komplette 
Programm, vielleicht kann man das dann besser nachvollziehen.
1
#define F_CPU     3686400            //Taktfrquenz
2
#define BAUD    19200            //einstellte Baudrate
3
//------------------------
4
#define AT_Anrufen  "atd0160xxxxxxx;\r"    //AT-Befehl für einen Anruf
5
#define AT_Auflegen  "ath\r"            //AT-Befehl für das Auflegen
6
#define AT_Temp    "at+cmte?\r"        //AT-Befehl für Temperaturabfrage
7
#define AT_Signal  "at+csq\r"          //AT-Befehl für Signalstärke
8
#define AT_Guth    "atd*100#\r"        //AT-Befehl für Guthabenabfrage
9
#define Ant_Temp  "+CMTE:"          //Antwort für Temperatur
10
#define Ant_Guth  "+CUSD:"          //Antwort für Guthaben
11
#define Ant_Signal  "+CSQ:"            //Antwort für Singalstärke
12
//------------------------
13
#define LED_Alarm_An  PORTB |= (1 << PB0);  //Kontroll-LED an "Alarm ausgelöst"
14
#define LED_Alarm_Aus  PORTB &= ~(1 << PB0);  //Kontroll-LED aus "Alarm ausgelöst"
15
//------------------------
16
#include <avr\io.h>                //zur Deklaration der Ports
17
#include <ctype.h>                //zur Verwendung von toupper
18
#include <string.h>                //zur Stringverwendung
19
#include "D:\Programmieren\Mikrocontroller\AVR\Header\uart.h"
20
#include "D:\Programmieren\Mikrocontroller\AVR\Header\interrupt.h"
21
#include <avr/io.h>
22
//----------------------------------------------------------------------
23
char _buffer[100];                //Globaler Schreibpuffer
24
int _i = 0;                    //globale Laufvariable
25
//----------------------------------------------------------------------
26
//----------------------------------------------------------------------
27
void initPorts() 
28
{
29
  //Ports B.0/1 als Ausgänge deklarieren
30
  DDRB = (1<< PB0)|(1<<PB1); 
31
  //Ports D.2/3 als Eingänge deklarieren
32
  DDRD = (0<<PB2)|(0<<PB3);
33
  // PORTD = PULL-UP
34
  PORTD = 0x04;                            
35
}
36
void Puffer_loeschen()
37
{
38
  for (int i=0; i<100; i++)
39
  {
40
    _buffer[i] = 0;
41
  }
42

43
  _i = 0;
44
}
45
void Anrufen()
46
{
47
  Puffer_loeschen();              //Puffer löschen
48
  putString(AT_Anrufen);            //Anrufen
49
  waitMs(15000);                //Zeit abwarten
50
  putString(AT_Auflegen);            //Auflegen
51
  waitMs(15000);                //bis zum nächsten Alarm warten
52
  Puffer_loeschen();              //Puffer löschen
53
}
54
char *Status(char *AT_Befehl, char *Antwort, int TimeOut)
55
{
56
  char *Rueckgabe = NULL;
57
  int i = 0;
58

59
  Puffer_loeschen();              //Puffer löschen
60
  putString(AT_Befehl);            //AT-Befehl senden
61
  waitMs(TimeOut);              //etwas warten
62

63
  while(!(strstr (_buffer, Antwort)))      //falls vorhanden Antwort prüfen
64
  {
65
    waitMs(1000);              //etwas Zeit verbummeln beim warten
66
    
67
    //falls die Zeit überschritten wird, "Error" als Rückgabewert übertragen und
68
    //die Schleife vorzeitig beenden. Sonst kann es zu Endlosschleifen kommen.
69
    if (i>=10)     
70
    {
71
      Rueckgabe = "Error";        //"Error" zurückgeben, falls keine Antwort
72
      goto ende;              
73
    }
74
    i++;
75
  }
76

77
  Rueckgabe = strstr (_buffer, Antwort);    //Wert in Variable schreiben
78
  strcat(Rueckgabe, "\r\n");
79
  ende:                    //Sprungmarke für Vorzeitige Beendung
80
  Puffer_loeschen();              //Puffer löschen
81
  putString(Rueckgabe);            //zu Testzwecken
82
  return Rueckgabe;              //Antwort als Rückgabewert
83
}
84
ISR(USART_RXC_vect)               //USART, Rx Complete
85
{
86
  char data = 0;
87
  data = getChar();              //Zeichen holen
88
  _buffer[_i] = data;
89
  _i++;
90
  //data = toupper(data);            //in große Zeichen umwandeln
91
}
92
//----------------------------------------------------------------------
93
//----------------------------------------------------------------------
94
main()                      //Hauptschleife
95
{
96
  initPorts();
97
  initUART();
98
  initInterrupt();
99

100
  do
101
  {
102
    //Alarm ausgelöst
103
    if (!(PIND & (1 << PD2))) 
104
    {
105
      waitMs(1000);            //etwas Zeit verbummeln
106
      if (!(PIND & (1 << PD2)))      //Alarm steht immernoch an
107
      {
108

109
        LED_Alarm_An;          //Kontroll-LED an "Alarm ausgelöst"    
110
        //Anrufen();          //Anrufen
111
        LED_Alarm_Aus;          //Kontroll-LED aus "Alarm ausgelöst"
112

113
        Status(AT_Signal, Ant_Signal, 500);
114
        //Status(AT_Temp, Ant_Temp, 500);
115
        //Status(AT_Guth, Ant_Guth, 500);
116
      }
117
    }
118

119
    Puffer_loeschen();          //Wenn mit den Daten nichts gemacht wird, werden sie gelöscht
120
  }
121
  while (true);
122
}

...un die Header
1
Uart.h
2
//Taktfrequenz
3
#ifndef F_CPU 
4
  #define F_CPU 3686400
5
#endif
6

7
//Baudrate
8
#ifndef BAUD 
9
  #define BAUD 19200
10
#endif
11

12
//UART-Schnitstelle initialisieren
13
void initUART() {
14
    UBRRL = (F_CPU / BAUD - 16) / 16;       //Baudberchnnung
15
    UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);    //Receiver/Transmitter/Receiver-Interrupt zulassen
16
    UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // Asynchron 8N1 
17
}
18

19
//Zeichen senden
20
void putChar(char data)  {
21
  while (!(UCSRA&32));          //warte bis UDR leer ist
22
  UDR = data;                //senden
23
}
24

25
//ganze Strings senden
26
void putString(char buffer[]) {
27
  for (int i=0 ; buffer[i] !=0 ; i++)
28
    putChar(buffer[i]);
29
}
30

31
//Zeichen empfangen
32
char getChar()                
33
{
34
  char data=0;
35
  while (!(UCSRA&128));           //warte bis RX-complete RXC UCSRA
36
  data=UDR;                 //empfangen
37
  return data;              //empfanges Zeichen übertragen
38
}
1
interrupt.h
2
//Interrupt initialisieren
3
#include <avr/interrupt.h>
4

5
void initInterrupt() {
6
  sei();                  // Interrupts zulassen
7
}
#2408554
Lesenswert?

Peter F. schrieb:
> An den Feinschliff kann man noch arbeiten, da gebe ich dir recht. Nur
> ich versuch erstmal das eine Problem zu lösen bevor ich eine neues
> Baustelle aufmache.

Wenn ein Programm verworren ist, ist das kein Schönheitsfehler, sondern 
häufig die Ursachae dafür, die anderen Fehlerursachen nicht zu finden.

Ebenso wie man eine planvolle Vorgehensweise und die Doku nicht erst 
hinterher macht, dann kann man es sich auch sparen.

Zumal du nicht nur deine Zeit damit verschwendest.
OP #2408576
Lesenswert?

Also ehrlich gesagt erdachte ich mir eine eventuelle schnelle Lösung des 
Problems und keine "Vorträge" über die Programmiervariante. Wenn dass 
das Problem ist, werde ich es natürlich ändern. Nur durch testen der 
einzelne Funktionsabschnitte, glaube ich immernoch dass das Problem bei 
der übergabe der Daten in die Variable "Rueckgabe" ist. Und die übergabe 
funktioniert ist ja schliesslich, sonst würde ich ein "Error" bekommen. 
Das habe ich auch mittel einen Suchstring getestet, der auf keinen Fall 
im Puffer sein kann.
#2408602
Lesenswert?

Die fehlenden volatile sind auf jeden Fall falsch.
Dabei ist schwer vorherzusagen, ob das das einzige Problem ist.

Also räumt man doch das schon mal zur Seite und sucht ggf. ohne
diese Fehler weiter.

Außerdem weiß ich jetzt ehrlich gesagt nicht, ob deine 
Fehlerbeschreibung noch zum letzten Programm passt.
Anrufen() wird ja gar nicht aufgerufen.
Kommt dann trotzdem etwas über die UART?
#2408869
Lesenswert?

Peter F. schrieb:
> glaube ich immernoch dass das Problem bei
> der übergabe der Daten in die Variable "Rueckgabe" ist.

Das Problem mit Rueckgabe wurde von Klaus Wachtler schon kurz 
angerissen, ist dann aber nicht weiter verfolgt worden (oder ich habe es 
übersehen).
1
  Rueckgabe = strstr (_buffer, Antwort);    //Wert in Variable schreiben
2
  strcat(Rueckgabe, "\r\n");
3
  ende:                    //Sprungmarke für Vorzeitige Beendung
4
  Puffer_loeschen();              //Puffer löschen
5
  putString(Rueckgabe);            //zu Testzwecken
6
  return Rueckgabe;              //Antwort als Rückgabewert
Der von strstr gelieferte Pointer zeigt auf die Fundstelle innerhalb 
von _buffer. Puffer_loeschen überschreibt _buffer komplett mit Nullen, 
und damit auch das, worauf Rueckgabe zeigt. Rueckgabe zeigt daher 
danach auf einen leerer String.
OP #2409638
Lesenswert?

Stefan Ernst schrieb:
> Der von strstr gelieferte Pointer zeigt auf die Fundstelle
> innerhalb von _buffer. Puffer_loeschen überschreibt _buffer komplett
> mit Nullen, und damit auch das, worauf Rueckgabe zeigt. /Rueckgabe/
> zeigt daher danach auf einen leerer String.

Oh man, natürlich. Ich hab einmal zu wenig um die Ecke gedacht. Danke, 
jetzt funktioniert es.

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