Hallo zusammen,
Ich habe eine Funktion geschrieben, die die Signalstärke eines
GSM-Moduls auswertet. Das ganze funktioniert über AT-Befehle.
Ich sende dem Modul AT+CSQ<ENTER> und das Modul antwortet mit (z.B.)
+CSQ: 13,99 wobei 13 die endscheidende Zahl ist, die ich benötige. Meine
Funktion funktioniert beim ersten Durchlauf wunderbar, beim zweiten
Durchlauf bleibt die Funktion bei while(!(0 == ukbhit2())); am Anfang
der Funktion hängen.
Also sendet das Modul nichts mehr zurück beim zweiten Durchlauf! Wenn
ich die AT-Befehle aber über ein Terminal an das GSM-Modul sende, kriege
ich immer eine Antwort, auch wenn ich jede Sekunde sende. In meiner
main() rufe ich die Funktion nur alle 3 sec auf. Also Zeit genug sollte
das Modul haben, also liegt es nicht am Modul.
Noch zusätzlich:
Ich habe keine Datenflußkontrolle aktiv.
Auch delay-Schleifen an verschiedensten Stellen in der Funktion, ergaben
keine Besserung.
Wieso sendet das Modul nichts zurück, aber mit einem Terminal schon?!?
Unabhängig von deinem eigentlichen Problem (dazu müsste man nämlich mal
wissen, welchen USART-Code du überhaupt verwendest, damit man mal weiß,
was ukbhit2 überhaupt macht, oder machen soll):
1
strncpy(gsmtemp,gsmsatz,8);//Die ersten 8 Zeichen des Strings kopieren
2
gsmtemp[8]='\0';
3
strrev(gsmtemp);//String umdrehen
4
strncpy(gsmtemp2,gsmtemp,2);//Die ersten 2 Zeichen des Strings kopieren
5
gsmtemp2[2]='\0';
6
strrev(gsmtemp2);
Wozu einfach, wenn es auch kompliziert geht, gell? ;-)
Problem gelöst:
Ich habe bevor ich den AT-Befehl übergebe noch zwei kleine
while-Schleifen hinzugefügt, die überprüfen ob Zeichen vorhanden sind
und diese dann bis zum Zeilenende verwerfen.
Damit sieht meine Funktion so aus:
1
chargsmtmp[3];
2
char*GsmSignalAbrufen(void)
3
{
4
uint8_ti=0;
5
chargsmzeichen;
6
chargsmsatz[20];
7
8
while(!(0==ukbhit2()))
9
while(ugetchar2()!=10);
10
11
uputs2("AT+CSQ\r\n");//Eingabe AT-Befehl
12
13
while(ugetchar2()!=10);//Erste Zeile bis Linefeed (\r\n) einlesen und verwerfen
14
do// Kompletten Datensatz empfangen
15
{
16
gsmzeichen=ugetchar2();// Zeichen vo USART einlesen
17
gsmsatz[i]=gsmzeichen;// Zeichenkette erweitern
18
i++;
19
}while(gsmzeichen!=10);// Zeilende v. Datensatz erkennen
20
21
strncpy(gsmtmp,gsmsatz+6,2);//Benötigte Zahl in gsmtmp speichern
im grunde kann man einiges anders machen ...
weil man das modul ja auch für andere befehle brauch
kann man einige sachen verallgemeinern
zB das wegsenden als funktion ..
entweder mit timeout und verwerfen oder neu senden
Abgesehen von dem obigen Diskussionsgegenstand gibt es noch ein weiteres
Problem mit dem aufgeführten Programmcode.
Die Startadresse des Arrays gsmtmp[] wird zurückgegeben. Leider handelt
es sich dabei jedoch um eine lokale Variable, deren Gültigkeit mit dem
Verlassen von GsmSignalAbrufen() endet. Zwar ist der zurückgegebene
Zeiger gültig, jedoch zeigt er auf einen freigegebenen Speicherbereich.
Das kann zwar gutgehen, da der Speicher nicht sofort gelöscht wird,
muss es aber nicht. Sobald der Stack z.B. durch weitere Funktionsaufrufe
wieder neu
belegt wird, werden auch die Daten überschrieben.
Es gibt mehrere Möglichkeiten, die obigen Probleme zu vermeiden:
1. Übergabe eines vorab definierten Puffers an GsmSignalAbrufen()
2. Anforderung von dynamischem Speicher innerhalb von GsmSignalAbrufen()
und Freigabe nach Verarbeitung des Inhaltes. ACHTUNG: SEHR SCHLECHTER
PROGRAMMIERSTIL, da äußerst fehlerträchtig.
3. Deklaration von gsmtmp[] als static-Variable. ACHTUNG: Mäßig
schlechter Programmierstil, da hierbei implizit angenommen wird, dass
die Adresse einer lokalen Variable auch außerhalb der Funktion
wohldefiniert und konstant ist.
Andreas Schweigstill schrieb:> Die Startadresse des Arrays gsmtmp[] wird zurückgegeben. Leider handelt> es sich dabei jedoch um eine lokale Variable
Schau nochmal genau hin.
Stefan Ernst schrieb:> Schau nochmal genau hin.
Upps, da habe ich mich in der Tat verguckt. Ich war gedanklich noch bei
gsmtemp2[] aus dem ersten Quelltext, wo jedoch auch alles richtig
übergeben wird. :-(