SIM900 AT命令响应解析

Ral*_*lph 1 sms arduino at-command sim900

我正在使用连接到Arduino Uno的sim900 gps/gprs模块屏蔽,我将如何解析我的AT命令的响应?或者,如何在发送AT命令后删除序列中打印的第1行?

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
Run Code Online (Sandbox Code Playgroud)

在上面的输出示例中,我想摆脱AT + CMGL ="ALL"然后解析左边的数据,解析的最佳方法是什么

hlo*_*dal 6

我怎样才能解析AT命令的响应?

是的,这是一个正确的问题.

发送AT命令后,如何删除序列中打印的第1行?

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

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

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

现在对于AT+CMGL命令来说,由于响应被分成多行,因此它的工作量稍微多一些.

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

文本模式下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>[...]]
Run Code Online (Sandbox Code Playgroud)

因此,在收到以"+ CMGL:"开头的行之后,直到您读取空白行("\ r \n")之后的所有行都属于此行.

关于通用代码结构和流程,请参阅此答案,尽管如上所述,响应的多行属性需要更多处理.我会使用类似下面的内容(未经测试的代码):

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))
Run Code Online (Sandbox Code Playgroud)