我一直在开发一个应用程序,它使用 GSM 调制解调器来做两件事之一;通过向服务器发送 GET 请求或向服务器发送数据(使用 UDP),使用内置 HTTP 堆栈检查其状态。我已经尝试了几种不同的方法来尽可能地保持它的可靠性,我终于准备好寻求帮助了。
我的应用程序是为 SIMCOM908 模块和 PIC18 平台编写的(我使用 PIC18 Explorer 进行开发)。
所以问题有时是调制解调器忙于做某事,并错过了一个命令。作为人类,我会看到并重新发送命令。为我的 MCU 添加超时和重新发送功能不是问题。
问题是调制解调器在不同事件之后发送未经请求的响应。当调制解调器更改注册状态(与手机信号塔)时,它会+CGREG: 1, ...
在 GPS 就绪时或当 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 位微控制器上运行!