Forum: Mikrocontroller und Digitale Elektronik Antwort auf AT Befehl. Wie das Ende erkennen?


von 0Fh (Gast)


Lesenswert?

Hallo Forum,

nach langem googlen, weiß ich momentan nicht mehr weiter.
Ich schreibe gerade eine kleine Applikation, die mit verschiedenen 
Modems Verbindungen aufbauen soll. Dazu sende ich AT Befehle an das 
Modem. Nun habe ich folgendes Problem:

Bisher habe ich das Ende der Antwort auf einen AT Befehl daran erkannt, 
dass ich auf ein
<CR><LF>OK<CR><LF>, bzw. ein
<CR><LF>ERROR<CR><LF> gewartet habe.

Das Ganze ging bisher auch nur, weil ich mit +CMEE=0 dem Modem 
mitgeteilt habe, dass es mir keine Fehlercodes, sondern einfach nur 
"ERROR" ausgeben soll.

Nun gibt es jedoch noch weitere AT Befehle, die wiederum 
unterschiedliche Antworten liefern können. Auf einen Anruf (ATD<Nummer>) 
kann u. a. ein
<CR><LF>CONNECT<CR><LF> oder ein
<CR><LF>NO CARRIER<CR><LF> geliefert werden.

Ich denke das es hier noch viel mehr Antwortmöglichkeiten gibt, die ich 
noch nicht abdecken konnte, daher die Frage:

Hat jemand Erfahrung mit AT Befehlen und weiß evtl. wo es eine 
verlässliche Übersicht (am besten eine Spec.) gibt. In der alle 
Antwortmöglichkeiten abgedeckt werden, bzw. eine Idee wie ich das Ende 
einer Antwort auf einen AT Befehl erkennen kann?

Vielen Dank schon einmal!

von Peter (Gast)


Lesenswert?


von Ollz (Gast)


Lesenswert?

Allgemein (Ausnahme siehe unten) variieren AT-Befehle und die Antworten 
stark von Gerät zu Gerät. Deine beste Hoffnung ist es, genau für dein 
Gerät eine Befehlsliste zu bekommen.

Für einige Geräteklassen, zum Beispiel Mobiltelefone, hat sich die 
Industrie die Mühe gemacht, detailliertere Standards festzulegen und 
viele Hersteller halten sich sogar an die Standards. Solche Standards 
wären mein zweiter Ansatz um an Informationen zu kommen.

Mein dritter Ansatz wäre den Protokoll-Parser flexibel zu schreiben, so 
dass er zum Beispiel Antworten wie "CONNECT" <beliebige Zeichen> 
<CR><LF> versteht.

von Arne (Gast)


Lesenswert?

Ich denke, dass der AT befehlssatz (soweit ich mich an mein Zyxel 1496E+ 
erinnern kann) auch herstellerspezifische Erweiterungen beinhaltet.
Warum empfängst Du nicht solange bis das zweite <LF> vom Modem 
eintrudelt?

von 0Fh (Gast)


Lesenswert?

@ Peter:
Werde mir den Link gleich anschauen. Vielen Dank schon Mal!

@ Ollz:
1. Das Problem ist, dass ich gerne mehrere Geräte unterstützen möchte 
:(. Für mein Gerät hier habe ich sogar eine Spec. ergattern können!

2. Auf solche einen Standard hoffe ich. Zumindest kann ich dann sagen 
das ich nach Standard X gearbeitet habe und ich nichts für kann, wenn 
die anderen sich nicht dran halten ;). Kennst du einen solchen Standard 
zufälligerweise, bzw. hast einen Ansatz wie und wo man ihn finden 
könnte?

3. Oh das mit dem dynamischen erkennnen kann irgendwie schwierig werden 
fürchte ich...
Ich hatte aber bereits die Vermutung, dass die Antwort immer an einem 
Stück erfolgt. Daher habe ich kurz darüber nachgedacht nach dem Empfang 
des ersten Antwortbytes einfach einen Timeout zu starten. Sobald ich 
dann X ms/s kein Byte mehr erhalten habe könnte ich davon ausgehen, dass 
die Antowrt komplett ist. Ist das vielleicht eine Möglichkeit?

@ Arne:
Das zweite <LF> geht leider nicht :(. Spontan fallen mir zwei Beispiele 
dazu ein:
1. AT+CSQ? liefert zum Beispiel die Empfangsstärke bei einer GSM 
Karte/Handy und hat folgendes Antwortformat:
<CR><LF>%s<CR><LF><CR><LF>OK<CR><LF> (e.g. "AT+CSQ")
2. Es kann sein dass die Karte ein Echo macht. Sendet man dann 
AT<CR><LF>
antwortet sie:
AT<CR><LF><CR><LF>OK<CR><LF> :(

Wer hat den Kram eigentlich erfunden *grrr.
Habe noch Hoffnung dass es irgewendwie geht, da es dieser Felder für 
benutzerspezifische Initialisierungskommandos in Widows gibt...

von Stefan R. (srausse)


Lesenswert?

zwei Anmerkungen bzw. Vorschläge von mir:

1. Ein Befehl zum Modem fängt immer mit "AT" (Ausnahme "A/") an und hört 
mit <CR> auf. Ein <LF> muss nicht mitgeschickt werden.

2. Empfangene Daten beginnen mit <CR> <LF> und werden mit <CR> <LF> 
abgeschlossen. Bei einem AT+CSQ? gibt es halt zwei Antworten, nämlich:

a.) <CR><LF>%s<CR><LF> und
b.) <CR><LF>OK<CR><LF>

Deine Software muss dann nur die korrekte Start- und Stopbedingung 
erkennen. In meinem Fall verwende ich dafür eine Statemachine:
1
  void gsm_rx_frame (void) {
2
  u8 byte;
3
  
4
  while ((gsm.uart->rx_rd!=gsm.uart->rx_wr)&&(!(gsm.flag&(1<<GSM_RX_TGR)))) {  // Solange Auswerten wie was im Empfangspuffer liegt      
5
    byte = gsm.uart->rx_buf[gsm.uart->rx_rd];
6
    gsm.uart->rx_rd = (gsm.uart->rx_rd+1) % RX_BUF;              // Pointer hochzählen (Ringpuffer!)
7
8
    switch (gsm.uart->rx_state) {
9
      case GSM_WAIT:   {if (byte==CR)   {gsm.uart->rx_state++;}  break;}    // Kein Telegramm angefangen, Abfrage des ersten Startbyte
10
      case GSM_START: {                          // Empfang des zweiten Startbytes bewerten
11
        if (byte==LF) {
12
          gsm.uart->rx_bytes = 0;                    // Zähler für empfangene Bytes zurücksetzen
13
          gsm.uart->rx_state++;                     // -> in den nächsten State
14
          }                                                      
15
        else {gsm.uart->rx_state--;}                  // ansonsten zurück!
16
        break;
17
        }
18
      case GSM_DATEN: {                          // Abspeichern der empfangenen Daten
19
        gsm.uart->rx_daten[gsm.uart->rx_bytes++] = byte;
20
        if (byte==CR) {gsm.uart->rx_state++;}              // CR ist der erste Teil vom Ende -> daher auf LF prüfen
21
        if (gsm.uart->rx_bytes>=RX_DATEN) {                // Zuviele Daten empfangen? -> Wieder auf die Startbedingung warten
22
          gsm.uart->rx_state=GSM_WAIT;
23
          }
24
        break;
25
        }      
26
      case GSM_END: {                            // Überprüfung auf das Ende
27
        gsm.uart->rx_daten[gsm.uart->rx_bytes++] = byte;
28
        if (byte==LF) {                          // LF ist der zeite Teil vom Ende -> daher 
29
          gsm.flag       |= (1<<GSM_RX_TGR);            // komplette Antwort erhalten
30
          gsm.uart->rx_timeout = GSM_RX_TIMEOUT;            // Timeout zurücksetzen  
31
          gsm.uart->rx_state   = GSM_WAIT;              // wieder auf Anfang stellen
32
          }
33
        else {gsm.uart->rx_state--;}                  // ansonsten in vorherigen State zurückgehen
34
        if (gsm.uart->rx_bytes>=RX_DATEN) {                // Zuviele Daten empfangen? -> Wieder auf die Startbedingung warten
35
          gsm.uart->rx_state=GSM_WAIT;
36
          }
37
        break;
38
        }      
39
      }
40
    }      
41
  }

Durch das gesetze Flag kann ich in meinem weiteren Routinen die 
empfangenen Daten schön sauber auf ihre Nutzdaten hin bewerten...

Bezogen auf AT+CSQ? würde die Routine natürlich zweimal das Flag setzen, 
aber nach dem ersten Telegramm erstmal aufhören weiter zu bewerten!

Gruß
Stefan

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.