Modemantwort von Siemens M20 verarbeiten ?

Gast #1057158
Hallo Leute,
ich hoffe, dass mir einer bei meinem Problem behilflich sein kann.
Und zwar versende ich bei einem Ereignis mehrere SMS über einen 
Atmega32. Hierbei treten jedoch regelmäßig Fehler auf, so dass mehrer 
SMS nicht gesendet werden. Um diese Fehler zu behandeln, möchte ich den 
Ergebniscode den mir das Modem schickt gerne auslesen und darauf 
dementsprechend reagieren. (So dass die SMS evt. nochmal gesendet wird)
Dies wollte ich mit folgenden Methoden realisieren:

/* Zeichen empfangen */
uint8_t uart_getc(void)
{
    while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
        ;
    return UDR;                   // Zeichen aus UDR an Aufrufer 
zurueckgeben
}

void uart_gets( char* Buffer, uint8_t MaxLen )
{
  uint8_t NextChar;
  uint8_t StringLen = 0;

  NextChar = uart_getc();         // Warte auf und empfange das nächste 
Zeichen

                                  // Sammle solange Zeichen, bis:
                                  // * entweder das String Ende Zeichen 
kam
                                  // * oder das aufnehmende Array voll 
ist
  while( NextChar != '\n' && StringLen < MaxLen - 1 ) {
    *Buffer++ = NextChar;
    StringLen++;
    NextChar = uart_getc();
  }

                                  // Noch ein '\0' anhängen um einen 
Standard
                                  // C-String daraus zu machen
  *Buffer = '\0';
}




Wenn ich zum testen Daten über das Hyperterminal sende, werden diese 
durch die obenstehenden Methoden richtig erfasst. Die eigentliche 
Aufgabe, den Ergebniscode des Modems abzufangen, wird jedoch nicht 
erfüllt...dies funktioniert nicht. Er hängt sich bei: NextChar = 
uart_getc();  Obwohl ja Daten vom Modem gesendet werden...!? Wie gesagt 
über's Hyperterminal funktionierts.
Würde mich über jede Hilfe freuen!

Vielen Dank im Vorraus
Gruß Thomas
Persönliche Seite #1057180
Hängt es bereits im ersten uart_getc()?

Dann könnte z.B. die Hardware nicht stimmen (TXD vom Modem über 
Pegelwandler an RXD vom AVR?) oder die im Codefetzen nicht sichtbare 
UART-Initialsierung ist falsch. Beides schliesse ich aus, weil du 
schreibst, dass die Übertragung AVR-Hyperterminal funktioniert.

Hängt es in einem der uart_getc() in der while-Schleife?

Bist du sicher, dass ein Zeilenende kommt und wenn dass dann ein '\n' 
(LF, Unix-Style) am Zeilenende steht und nicht ein '\r' (CR, Mac-Style) 
oder ein '\r' und ein '\n' (CRLF, PC-Style)? Wie verhält sich das Modem 
an Hyperterminal (besser wäre z.B. Br@y-Terminal o.ä. bei denen man die 
Einzelzeichen hexadezimal anzeigen kann).
Gast #1057186
ja...das die Hardware nicht stimmt kann man ausschließen. mit 
Hyperterminal geht ja alles. Das ist ja gerade das Merkwürdige.
ich habe mich ja auch im Hyerterminal und mit einem RS232 Sniffer davon 
überzeugt, dass eine Antwort zurückkommt...und welche Datenpakete 
gesendet werden.

Ja es hängt so wie es aussieht schon bei der ersten Abfrage.
Ich habe es auch schon mit

"while( StringLen < MaxLen - 1 )"

statt


"while( NextChar != '\n' && StringLen < MaxLen - 1 )"


probiert... dass hat aber auch nicht funktioniert.?
Persönliche Seite #1057235
Thomas wrote:

> Ja es hängt so wie es aussieht schon bei der ersten Abfrage.

Wenn du Position ### 1 meinst (s.u.), dann verstehe ich nicht was das 
folgende bringen soll:

> Ich habe es auch schon mit
>     while( StringLen < MaxLen - 1 )
> statt
>     while( NextChar != '\n' && StringLen < MaxLen - 1 )
> probiert... dass hat aber auch nicht funktioniert.?
1
void uart_gets( char* Buffer, uint8_t MaxLen )
2
{
3
  uint8_t NextChar;
4
  uint8_t StringLen = 0;
5

6
  // Warte auf und empfange das ERSTE Zeichen
7
  NextChar = uart_getc();    // ### 1 
8

9
  // Sammle solange Zeichen, bis:
10
  // * entweder das String Ende Zeichen kam
11
  // * oder das aufnehmende Array voll ist
12
  
13
  while( NextChar != '\n' && StringLen < MaxLen - 1 ) 
14
  {
15
    *Buffer++ = NextChar;
16
    StringLen++;
17
    NextChar = uart_getc();  // ### 2
18
  }
19

20
  // Noch ein '\0' anhängen um einen Standard
21
  // C-String daraus zu machen
22
  *Buffer = '\0';
23
}

Bei dem Code läuft du in einen Hänger, wenn nie ein '\n' kommt und wenn 
nie mehr oder gleichviel Zeichen wie MaxLen-1 gesendet werden. Durch 
Weglassen der Prüfung auf '\n' verschlimmerst du die Situation.

Den CR-Fall könntest du so abfangen:

  while( NextChar != '\r' && NextChar != '\n' && StringLen < MaxLen - 1 
)

Es ist auch wichtig, wie der Rest des Programmes konstruiert ist. Wenn 
das Modem im Normalfall keine Statusmeldungen schickt, würde eine 
ständige Prüfung auf Statusmeldungen mit uart_gets() immer zur Blockade 
führen.

Dieses uart_gets ist ja wegen uart_getc an Pos. ### 1 und wegen dem 
while inkl. ### 2 grundsätzlich blockierend.

Man könnte das ändern, indem man z.B. die Daten nebenläufig zum 
Userprogramm in einem RX-Interrupt empfängt, einen Puffer füllt und im 
Programm je nach Füllgrad des Puffers darauf reagiert.

Wenn es ohne Interrupt gehen soll, könnte vor dem Aufruf der uart_getc 
prüfen, ob in der UART Daten vorliegen und dann - und nur dann - dorthin 
verzweigen.
1
void uart_gets( char* Buffer, uint8_t MaxLen )
2
{
3
  uint8_t NextChar;
4
  uint8_t StringLen = 0;
5

6
  // Wenn ein Zeichen in der UART vorhanden ist, 
7
  // dann empfange das als ERSTES Zeichen einer 
8
  // Statusmeldung
9

10
  if ((UCSRA & (1<<RXC)))
11
  {
12
    NextChar = uart_getc();    // ### 1 
13

14
    // Sammle solange Zeichen, bis:
15
    // * entweder das String Ende Zeichen kam
16
    // * oder das aufnehmende Array voll ist
17
    while( NextChar != '\n' && StringLen < MaxLen - 1 ) 
18
    {
19
      *Buffer++ = NextChar;
20
      StringLen++;
21

22
      // Mit der Annahme, dass dann noch 
23
      // mehr Zeichen kommen, darauf warten...
24
      NextChar = uart_getc();  // ### 2
25
    }
26
  }
27

28
  // Noch ein '\0' anhängen um einen Standard
29
  // C-String daraus zu machen
30
  *Buffer = '\0';
31
}
Persönliche Seite #1057280
ADD:

In dem letzten Vorschlag würde ich aber den Namen der Funktion ändern, 
weil der normale µC-Programmierer davon ausgeht, dass uart_gets auf 
Gedeih und Verderb auf einen String wartet. Damit dass eine so benannte 
Funktion ohne String (bzw. einem Leerstring) zurückkommt, rechnet er 
eigentlich nie oder selten ;-)
Gast #1057332
OK vielen Dank für die Vorschläge. Bin noch relativ neu in diesem 
Gebiet. Ich werde es nun mal mit einem Empfangs-Interuppt versuchen und 
einen Puffer vollschreiben...den ich in der Hauptroutine auslesen falls 
das entspechende Flag gesetzt ist.
Wobei es mir immer noch unverständlich ist, wieso er mit dem bisherigen 
Code nichts auslesen konnte (also jedenfalls nicht die Daten vom Modem).
Gast #1061337
Ich habe das Problem nun wie oben beschrieben gelöst. Jetzt habe ich ein 
anderes Problem.... muss nun zum Abschluss noch die ca. 30 Nummern in 
ein Array etc. hinterlegen. Weiß aber nicht genau in welcher 
Datenstrucktur.
kann mir einer einen Vorschlag machen?

mit:

char Number[30];
Nummer[0] = "+49...."; geht es ja nicht !???
Persönliche Seite #1061462
Thomas wrote:

> char Nummer[30];   //  <--- meine ich natürlich
> Nummer[0] = "+49...."; geht es ja nicht !???

Beginner
1
char *Nummer[30] = {
2
    "+49...",
3
    "+49...",
4
    "+49...",
5
    "+49...",
6
    // usw.
7
    "+49..."
8
};

Vergleiche im Programm mit strcmp()

Intermediate
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Vereinfachung_f.C3.BCr_Zeichenketten_.28Strings.29_im_Flash

Expert
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Array_aus_Zeichenketten_im_Flash-Speicher

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.