AT命令响应(理解Arduino上代码执行的顺序)
我正在从Arduino Uno / Nano(ATmega328)向ESP8266发送AT命令并试图解析收到的字符串的结尾,以确定ESP如何反应以及它是否成功(以及它是否已准备好接收另一个命令然而)。 我知道解析AT命令响应之前已经讨论过了: 获取AT命令响应
但是我有一个特定的问题,那里的其他人可能也会感兴趣…
首先,调用一个函数,它将AT命令发送到ESP以连接到ThingSpeak(数据记录服务器)。 这在手动模式下工作正常,并且在尝试解析响应时也连接但是它只解析返回的第一行。 例如,串行监视器中的预期输出将是:
c AT+CIPSTART="TCP","api.thingspeak.com",80 CONNECT OK Connected to ThingSpeak!
其中c
只是我输入的命令字符以启动连接。
但实际反应如下:
c AT+CIPSTART="TCP","api.thingspeak.com",80 Cannot connect to ThingSpeak! CONNECT OK
这意味着解析函数在收到响应之前结束…如下面的代码所示,当前指定了10秒的超时。 即使有20秒的超时,同样的事情发生了,尽管事实上,当手动执行时,响应在大约一秒钟内到达。
只是为了测试解析函数,我尝试搜索"80"
并返回true,因为这是在响应的第一行末尾找到的。 无论是搜索"OK"
还是"OK\r\n"
,结果都是相同的,它返回false,然后收到其余的响应。
这是代码:
boolean waitForResponse(String target, unsigned long timeout) { unsigned long startTime = millis(); String responseBuffer; char charIn; //keep checking for ESP response until timeout expires while ((millis() - startTime) < timeout) { if (ESP.available()) { responseBuffer += ESP.read(); } } Serial.println(responseBuffer); if (responseBuffer.endsWith(target)) { return true; } else { return false; } } void openCxn() { ESP.print("AT+CIPSTART=\"TCP\",\"api.thingspeak.com\",80"); delay(500); if (waitForResponse("80",10000L)) { Serial.println("Connected to ThingSpeak!"); } else { Serial.println("Cannot connect to ThingSpeak!"); } }
知道为什么它会在收到完整响应之前返回(在超时期限内)? 它与endsWith()
函数有关吗?
因此,您是否有任何想法如何使其解析整个响应而不仅仅是第一行?
重申一下,我只对结束响应感兴趣(例如"OK"
或"OK\r\n"
)。
知道为什么它会在收到完整响应之前返回(在超时期限内)?
是的,您的主要问题如下
if (ESP.available())
这使得只要UART(或其他一些串行IO缓冲区)为空,waitForResponse函数就会返回 – 这不是你想要的。 你想要的是从串口读取,直到你收到一个以"\r\n"
结尾的行。
它与endsWith()函数有关吗?
是的,这是与ESP.available
相结合的另一个问题,因为您试图将调制解调器的响应行的末尾与串行路径中发生的随机数据斩波相匹配。 如果你非常幸运,这将是在线边界,但很可能不是,你不应该依赖它。
这是一种称为成帧的通用协议问题,适用于任何类型的异步串行通信。 对于调制解调器通信,成帧字符是\r
和\n
。
帮自己一个忙,并实现一个一个字符读取的readline
函数,直到前一个字符是\r
并且当前字符是\n
然后返回它到目前为止读取的所有内容。
然后专门使用该function1来读取调制解调器响应数据。 这适用于中间结果代码(如CONNECT
)以及最终结果代码 (例如OK
等)。 然后,“解析”响应行可以如此简单
if (responseLine.equals("CONNECT\r\n")) ...
要么
if (isFinalResultCode(responseLine)) ...
正如我之前所说, 处理调制解调器输出的唯一正确方法是将输出分成完整的行,然后迭代一整行。
1唯一的例外是解析AT + CMGS响应数据。
你的if if while确实是错的因为你可能已经阅读了更多的东西,因此即使收到了ok,你也不会以目标字符串结束。
您应该只测试responseBuffer是否以目标结束并返回true仅当您在while循环中而不是之后收到新Char时。 超时后,只返回false。