Ich habe an einer Anwendung gearbeitet, die ein GSM-Modem für eines von zwei Dingen verwendet; Überprüfen Sie den Status mithilfe des integrierten HTTP-Stacks, indem Sie eine GET-Anforderung an den Server senden oder Daten an den Server senden (mithilfe von UDP). Ich habe verschiedene Methoden ausprobiert, um dies so zuverlässig wie möglich zu halten, und bin endlich bereit, um Hilfe zu bitten.Einen GSM-Modem-Treiber schreiben?
Meine Anwendung ist für das SIMCOM908-Modul und die PIC18-Plattform geschrieben (ich verwende einen PIC18 Explorer für die Entwicklung).
So ist das Problem manchmal das Modem ist beschäftigt, etwas zu tun, und verfehlt einen Befehl. Als Mensch würde ich das sehen und den Befehl einfach erneut senden. Das Hinzufügen einer Einrichtung für meine MCU zu Zeitüberschreitung und erneutem Senden ist kein Problem.
Ein Problem ist, dass das Modem unerwünschte Antworten nach verschiedenen Ereignissen sendet. Wenn das Modem den Registrierungsstatus ändert (mit dem Mobilfunkmast), antwortet es mit +CGREG: 1, ...
oder wenn das GPS bereit ist GPS Ready
. Diese Antworten können jederzeit auftreten, auch mitten in einem Befehl (z. B. beim Erstellen einer IP-Verbindung).
Das ist ein Problem, weil ich nicht über eine Möglichkeit nachgedacht habe, damit umzugehen. Meine Anwendung muss einen Befehl senden (um eine Verbindung zum Server herzustellen, z. B. AT+CIPSTART="UDP","example.com",5000
). Dieser Befehl antwortet mit 'OK' und dann, wenn der Befehl 'CONNECT OK' beendet ist. Ich muss jedoch in der Lage sein, auf die vielen anderen möglichen Antworten zu reagieren, und ich habe keinen Weg gefunden, dies zu tun. Was muss ich mit meinem Code tun? Warten Sie auf eine Antwort vom Modem, überprüfen Sie die Antwort, führen Sie eine Aktion basierend auf dieser Antwort durch?
Ich bin Code-begrenzt (ein 8-Bit-Mikrocontroller!) Und möchte die Keep-Wiederholung auf ein Minimum reduzieren. Wie kann ich eine Antwortfunktion schreiben, die eine Antwort vom GSM-Modul (angefordert oder jetzt) nimmt und dann den Rest meines Programms weiß, was passiert?
Idealerweise möchte ich etwas mit diesen Antworten tun. Wie halten einen internen Zustand (wenn ich GPS Ready
hören, ich weiß, dass ich die GPS mit Strom versorgen usw.
Vielleicht gibt es einige Dinge, die ich denken soll, oder vielleicht ist es ein Open-Source-Projekt, das bereits dieses Problem löst?
Hier ist, was ich bisher:..
/* Command responses */
enum {
// Common
OK = 0,
ERROR,
TIMEOUT,
OTHER,
// CGREG
NOT_REGISTERED,
// CGATT
NOT_ATTACHED,
// Network Status
NO_NETWORK,
// GPRS status
NO_ADDRESS,
// HTTP ACTION
NETWORK_ERROR,
// IP Stack State
IP_INITIAL,
IP_STATUS,
IP_CONFIG,
UDP_CLOSING,
UDP_CLOSED,
UDP_CONNECTING
} gsmResponse;
int gsm_sendCommand(const char * cmd) {
unsigned long timeout = timer_getCurrentTime() + 5000;
uart_clearb(GSM_UART); // Clear the input buffer
uart_puts(GSM_UART, cmd); // Send the command to the module
while (strstr(bf2, "\r") == NULL) { // Keep waiting for a response from the module
if (timeout < timer_getCurrentTime()) { // Check we haven't timed out yet
printf("Command timed out: %s\r\n", cmd);
return TIMEOUT;
}
}
timer_delay(100); // Let the rest of the response be received.
return OK;
}
int gsm_simpleCommand(const char * cmd) {
if (gsm_sendCommand(cmd) == TIMEOUT)
return TIMEOUT;
// Getting an ERROR response is quick, so if there is a response, this will be there
if (strstr(bf2, "ERROR") != NULL)
return ERROR;
// Sometimes the OK (meaning the command ran) can take a while
// As long as there wasn't an error, we can wait for the OK
while (strstr(bf2, "OK") == NULL);
return OK;
}
Ein einfacher Befehl ist jeder AT-Befehl, der speziell für OK
oder ERROR
in Antwort sucht so etwas wie AT
Allerdings habe ich es auch wie AT+CPIN?
für erweiterte Befehle verwenden, da es m eans Ich habe die ganze Antwort erfasst und kann weiter nach dersuchen. Nichts davon reagiert jedoch auf die unaufgeforderten Antworten. In der Tat wird die gsm_sendCommand()
Funktion früh zurückkehren, wenn die unaufgeforderte Antwort empfangen wird.
Was für eine gute Möglichkeit, komplexe, gelegentlich unerwünschte Statusmeldungen wie diese zu verwalten? Bitte beachten Sie, dass diese Anwendung in C geschrieben ist und auf einem 8-Bit-Mikrocontroller läuft!
Sie müssen wahrscheinlich eine Zustandsmaschine (FSM) implementieren: 'newstate = oldstate [message]', und vielleicht betrachten Sie das andere Ende auch als Zustandsmaschine. – wildplasser
Das wird ein Teil davon sein, denke ich. Eine vollständige FSM scheint in diesem Fall jedoch nicht die beste Option zu sein. Ich muss den binären Zustand einiger unangeforderter Codes verfolgen und nicht die verschiedenen Zustände eines einzelnen Systems. Ich werde einfach ein paar globale boolesche Typen haben, um den Überblick zu behalten. – dantheman