2016-04-25 119 views
1

我使用sim900 gps/gprs模块屏蔽连接到Arduino Uno,我将如何解析我的AT命令的响应?或者,如何在发送AT命令后删除串行打印的第一行?在上面的输出SIM900 AT命令响应解析

AT+CMGL="ALL" 

+CMGL: 1,"REC READ","+XXXXXXXXXX","","16/04/25,15:20:59+32" 
Hilp akp si ralphh the pogi one mmalit mi pizza hehehehehe 

+CMGL: 2,"REC READ","+XXXXXXXXXX","","16/04/25,21:51:33+32" 
Yow!!! 

OK 

例子,我想摆脱AT + CMGL =“所有”,然后离开了数据分析,什么是解析

回答

5

我将如何解析我的AT命令的响应?

是的,这是正确的问题。

如何在发送AT命令后删除串行打印的第一行?

不,这是一个错误的问题要问,因为如果你关心回声是否在打开,你是做错了。

用于解析AT命令输出正确的策略如下:

  • 发送AT命令行(与"\r"正确终止)。
  • 读取从调制解调器收到的一个字符和一个字符,直到完成一行以"\r\n"终止,然后解析该行。
    • 如果该行等于最终结果代码,则命令行的所有输出都已完成(并且调制解调器已准备好接收新命令)。这必须是您测试的第一件事!
    • 如果运行AT命令的信息文本响应行有前缀(几乎都有),请检查该行是否以该行开头,如果是,则处理该行,否则忽略它。
    • 如果运行的AT命令没有前缀,您可能需要打印所有内容,直到收到最终结果代码。这仅适用于像ATI这样的传统命令,并且对于解析这些命令您可能合法地关心是否回显。

现在为AT+CMGL命令是一点点的工作,因为响应在多行分割。

首先,最好的信息来源应该是制造商特定的AT文档,其次是标准化AT+CMGL命令的官方3GPP 27.005规范。

在文本模式下为AT + CMGL响应被指定为

+CMGL: <index>,<stat>,<oa/da>,[<alpha>],[<scts>][,<tooa/toda>, 
<length>]<CR><LF><data>[<CR><LF> 
+CMGL: <index>,<stat>,<da/oa>,[<alpha>],[<scts>][,<tooa/toda>, 
<length>]<CR><LF><data>[...]] 

因此接收开头的行之后“+ CMGL:”所有以下,直到读出的空行(行为“\ r \ n“)属于这个。

请参阅this answer关于一般的代码结构和流程,虽然如上面写的响应的多行属性需要多一点处理。我会用类似下面的(未测试的代码):

enum CMGL_state { 
    CMGL_NONE, 
    CMGL_PREFIX, 
    CMGL_DATA 
}; 

// Extra prototype needed because of Arduino's auto-prototype generation which often breaks compilation when enums are used. 
enum CMGL_state parse_CMGL(enum CMGL_state state, String line); 
enum CMGL_state parse_CMGL(enum CMGL_state state, String line) 
{ 
    if (line.equals("\r\n") { 
     return CMGL_NONE; 
    } 
    if (line.startsWith("+CMGL: ") { 
     return CMGL_PREFIX; 
    } 
    if (state == CMGL_PREFIX || state == CMGL_DATA) { 
     return CMGL_DATA; 
    } 
    return CMGL_NONE; 
} 

... 

write_to_modem("AT+CMGL=\"ALL\"\r"); 
CMGL_state = CMGL_NONE; 
goto start; 
do { 
    CMGL_state = parse_CMGL(CMGL_state, line); 
    switch (CMGL_state) { 
    case CMGL_PREFIX: 
     process_prefix(line); // or whatever you want to do with this line 
     break; 
    case CMGL_DATA: 
     process_data(line); // or whatever you want to do with this line 
     break; 
    case CMGL_NONE: 
    default: 
     break; 
    } 
start: 
    line = read_line_from_modem(); 
} while (! is_final_result_code(line)) 
+0

哇这是很多吸收,非常感谢你这个有用的信息我只是怀疑我的能力,完全实现这个,因为这是我第一次处理AT命令和解析,仍然有点有些部分有点困惑..非常感谢! – Ralph

2

第一行AT+CMGL="ALL"似乎是最好的方式成为回声。您可以通过在setup功能中向您的模块发送ATE0来禁用它。

至于其余的数据,它们都有相同的格式。您可以使用不同的字符串操作函数轻松编写解析器。

+0

圣洁非常感谢你!我一直在寻找一种方法来消除这些回声几天,但我仍然不知道如何解析数据,你能给我一个简单的例子,我可以使用吗? – Ralph

+0

@Ralph你的意思是像两个小时前[在Arduino网站上]已经给你的答案](http://arduino.stackexchange.com/questions/23575/split-string-into-an-array-of-串)? – frarugi87

+0

@ frarugi87是的,因为我不知道什么时候调用函数和什么参数,为什么它会返回一个int 1,并且当我尝试将序列存储到字符数组中时,我会得到随机字符 'if(mySerial。可用()> 0){ for(byte i = 0; i <99; i ++)str [i] = mySerial.read(); Serial.print(str [i]); } }' – Ralph

1

如果您正在使用arduino我会建议使用一个好的库!你不需要处理这些东西。尝试http://www.gsmlib.org/或者您可以找到任何您喜欢的其他人。

我会在这里列举一个例子。

#include "SIM900.h" 
#include <SoftwareSerial.h> 
//If not used, is better to exclude the HTTP library, 
//for RAM saving. 
//If your sketch reboots itself proprably you have finished, 
//your memory available. 
//#include "inetGSM.h" 

//If you want to use the Arduino functions to manage SMS, uncomment the lines below. 
#include "sms.h" 
SMSGSM sms; 

//To change pins for Software Serial, use the two lines in GSM.cpp. 

//GSM Shield for Arduino 
//www.open-electronics.org 
//this code is based on the example of Arduino Labs. 

//Simple sketch to send and receive SMS. 

int numdata; 
boolean started=false; 
char smsbuffer[160]; 
char n[20]; 

void setup() 
{ 
    //Serial connection. 
    Serial.begin(9600); 
    Serial.println("GSM Shield testing."); 
    //Start configuration of shield with baudrate. 
    //For http uses is raccomanded to use 4800 or slower. 
    if (gsm.begin(2400)){ 
    Serial.println("\nstatus=READY"); 
    started=true; 
    } 
    else Serial.println("\nstatus=IDLE"); 

    if(started){ 
    //Enable this two lines if you want to send an SMS. 
    //if (sms.SendSMS("3471234567", "Arduino SMS")) 
     //Serial.println("\nSMS sent OK"); 
    } 

}; 

void loop() 
{ 
    if(started){ 
    //Read if there are messages on SIM card and print them. 
    if(gsm.readSMS(smsbuffer, 160, n, 20)) 
    { 
     Serial.println(n); 
     Serial.println(smsbuffer); 
    } 
    delay(1000); 
    } 
};