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!
im wiki zu AT-Befelssatz ist http://www.iclinks.com/public_ftp/DocRelease/icl4300/ModemATCmdRef.pdf verlinkt.
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.
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?
@ 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...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.