我的应用程序是为SIMCOM908模块和PIC18平台编写的(我正在使用PIC18 Explorer进行开发).
所以问题有时候调制解调器正忙着做点什么,错过命令.作为一个人,我会看到,只是重新发出命令.为我的MCU添加一个设备来超时和重新发送不是一个问题.
调制解调器在不同的事件之后发送未经请求的响应是什么问题.当调制解调器更改注册状态(使用单元塔)时,它将使用CGREG:1,…或GPS准备好GPS准备就绪.这些响应可能在任何时候发生,包括在命令中间(如创建IP连接).
这是一个问题,因为我没有想到有办法处理这个问题.我的应用程序需要发送一个命令(例如,连接到服务器,AT CIPSTART =“UDP”,“example.com”,5000)此命令将响应“OK”,然后当命令完成“CONNECT OK ”.然而,我需要能够对许多其他可能的反应做出反应,而我也没有想到这样做.我需要做什么我的代码;等待来自调制解调器的响应,检查响应,根据该响应执行一个操作?
我是代码限制(作为一个8位微控制器!),并希望保持重复的最小.我如何编写一个响应函数,该函数将从GSM模块(请求或现在)获得响应,然后让我的程序的其余部分知道发生了什么?
理想情况下,我想和这些回应做一些事情.像保持内部状态(当我听到GPS准备好,我知道我可以为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; }
一个简单的命令是任何AT命令,专门寻找OK或ERROR作为响应.像AT这样的东西但是,我也使用它更高级的命令,如AT CPIN?因为这意味着我将捕获整个响应,并可以进一步搜索CPIN:READY.然而,没有一个实际上是对未经请求的回应的回应.实际上,gsm_sendCommand()函数将在收到非请求响应时提早返回.
管理复杂的偶尔不请自来的状态信息的好方法是什么?请注意,此应用程序是用C编写的,并运行在8位微控制器上!
解决方法
一些模块具有也可用于消息的辅助串行端口.如果可能,您可以将主动邮箱仅显示在单个串行端口上,而主端口则用于AT命令.这可能是不可能的,一些GSM模块将不支持辅助端口上的完整命令集.
也许更好的方法是禁用非请求的消息.大多数命令要求所有的状态.例如在等待注册时,而不是等待发出未经请求的注册消息,只需对当前注册状态的模块进行轮询.这允许您始终控制,您只需处理刚发送的命令的响应.如果您正在等待多个事件,您可以轮流对每个项目循环轮询.这通常会使代码更简单,因为您只需要一次处理单个响应.缺点是您的回应时间受到您的投票率的限制.
如果您继续采用未经请求的邮件方式,我建议为未经请求的邮件实施一个小队列.在等待命令的响应时,如果响应与命令不匹配,只需将响应推送到队列中即可.然后,当您收到AT命令的响应或超时时,您可以处理未经请求的消息队列.