我一直在开发一个应用程序,其中使用GSM调制解调器进行以下两种操作之一:使用内置的HTTP堆栈通过向服务器发送GET请求来检查其状态,或者使用UDP将数据发送到服务器。我尝试了几种不同的方法,以使这个过程尽可能可靠,并且现在我终于准备寻求帮助。
我的应用程序是为SIMCOM908模块和PIC18平台编写的(我正在使用PIC18 Explorer进行开发)。
问题在于有时调制解调器正忙于执行某些操作,会错过命令。作为人类,我会看到这一点并重新发送命令。添加MCU超时并重新发送的功能不是问题。
问题在于,调制解调器会在不同事件之后发送未经请求的响应。当调制解调器更改注册状态(与基站)时,它会响应
这是个问题,因为我还没有想到如何处理这个问题。我的应用程序需要发送一个命令(例如连接到服务器,
我的代码受限(是8位微控制器!),我希望将重复次数最小化。我该如何编写一个响应函数,以接收GSM模块(已请求或未请求)的响应,然后让我的程序知道正在发生什么?
理想情况下,我想对这些响应做一些事情。例如保持内部状态(当我听到
也许有些事情我应该考虑,或者也许有一个开源项目已经解决了这个问题?
以下是我目前的进展:
一个简单的命令是指特定寻找响应中的
如何管理这种复杂而偶尔未经请求的状态消息?请注意,此应用程序是用C编写的,并在8位微控制器上运行!
我的应用程序是为SIMCOM908模块和PIC18平台编写的(我正在使用PIC18 Explorer进行开发)。
问题在于有时调制解调器正忙于执行某些操作,会错过命令。作为人类,我会看到这一点并重新发送命令。添加MCU超时并重新发送的功能不是问题。
问题在于,调制解调器会在不同事件之后发送未经请求的响应。当调制解调器更改注册状态(与基站)时,它会响应
+CGREG: 1, ...
,或者当GPS就绪时GPS Ready
。这些响应可以在任何时间发生,包括在命令中间(例如创建IP连接)。这是个问题,因为我还没有想到如何处理这个问题。我的应用程序需要发送一个命令(例如连接到服务器,
AT+CIPSTART="UDP","example.com",5000
)。此命令将响应“OK”,然后当命令完成时响应“CONNECT OK”。然而,我需要能够对许多其他可能的响应做出反应,但我还没有想出一种方法来实现这一点。我需要在我的代码中做什么,才能等待调制解调器的响应,检查响应并根据该响应执行操作?我的代码受限(是8位微控制器!),我希望将重复次数最小化。我该如何编写一个响应函数,以接收GSM模块(已请求或未请求)的响应,然后让我的程序知道正在发生什么?
理想情况下,我想对这些响应做一些事情。例如保持内部状态(当我听到
GPS Ready
时,我知道可以开启GPS等)。也许有些事情我应该考虑,或者也许有一个开源项目已经解决了这个问题?
以下是我目前的进展:
/* 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;
}
一个简单的命令是指特定寻找响应中的
OK
或ERROR
的任何AT命令。例如AT
。然而,我还会使用它来执行更高级的命令,比如AT+CPIN?
,因为这意味着我将捕获整个响应,并可以进一步搜索+CPIN: READY
。但是,这些都不能响应未经请求的响应。事实上,当收到未经请求的响应时,gsm_sendCommand()
函数将会提前返回。如何管理这种复杂而偶尔未经请求的状态消息?请注意,此应用程序是用C编写的,并在8位微控制器上运行!
newstate = oldstate [ message ]
,并且也许要考虑另一端也是状态机。 - wildplasser