写GSM调制解调器驱动程序?

dan*_*man 10 c modem gsm pic gprs

我一直在研究一种使用GSM调制解调器的应用程序,用于以下两种方式之一; 通过向服务器发送GET请求或将数据发送到服务器(使用UDP),使用内置HTTP堆栈检查其状态.我已经尝试了几种不同的方法来保持尽可能可靠,我终于准备寻求帮助了.

我的应用程序是为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;
}
Run Code Online (Sandbox Code Playgroud)

一个简单的命令是任何专门寻找OKERROR响应的AT命令.有点像AT.但是,我也将它用于更高级的命令,AT+CPIN?因为这意味着我将捕获整个响应,并可以进一步搜索+CPIN: READY.然而,这些都不是对未经请求的回应的实际回应.实际上,gsm_sendCommand()当收到未经请求的响应时,该函数将提前返回.

管理像这样的复杂,偶尔未经请求的状态消息有什么好方法?请注意,此应用程序是用C语言编写的,并在8位微控制器上运行!

Aus*_*ips 3

必须在同一数据流中处理未经请求的消息以及对请求的响应是很困难的,因为您需要对传入流进行多路分离并将结果分派到适当的处理程序。它有点像中断处理程序,因为您必须放弃正在做的事情并处理您不一定期望的其他信息。

有些模块有一个辅助串行端口,也可用于发送消息。如果可能的话,您可以让未经请求的消息仅出现在单个串行端口上,而主端口用于您的 AT 命令。这可能是不可能的,并且某些 GSM 模块将不支持辅助端口上的完整命令集。

也许更好的方法是禁用未经请求的消息。大多数命令需要请求所有状态。例如,在等待注册时,无需等待主动注册消息的出现,只需轮询模块以获取当前注册状态即可。这使您始终处于控制之中,并且您只需处理刚刚发送的命令的响应。如果您正在等待多个事件,您可以依次循环轮询每个项目。这通常会使代码更简单,因为您一次只需处理一个响应。缺点是您的响应时间受到轮询率的限制。

如果您决定继续使用未经请求的消息方法,我建议为未经请求的消息实现一个小队列。在等待命令响应时,如果响应与命令不匹配,则只需将响应推送到队列中。然后,当您收到 AT 命令的响应或超时时,您可以稍后处理未经请求的消息队列。