C AT命令响应(了解Arduino上代码的执行顺序)
我正在从an/Nano(ATmega328)向an发送AT命令,并试图解析接收到的字符串的结尾,以确定ESP的反应方式以及是否成功(以及是否准备好接收另一个命令)。我知道前面已经讨论过在命令响应处解析: 但我有一个具体的问题没有涉及到这里,其他人可能也感兴趣 首先,调用一个函数,该函数将AT命令发送到ESP,以连接到ThingSpeak(数据记录服务器)。这在手动模式下工作良好,在尝试解析响应时也会连接,但它只解析返回的第一行。例如,串行监视器中的预期输出为:C AT命令响应(了解Arduino上代码的执行顺序),c,arduino,at-command,esp8266,ends-with,C,Arduino,At Command,Esp8266,Ends With,我正在从an/Nano(ATmega328)向an发送AT命令,并试图解析接收到的字符串的结尾,以确定ESP的反应方式以及是否成功(以及是否准备好接收另一个命令)。我知道前面已经讨论过在命令响应处解析: 但我有一个具体的问题没有涉及到这里,其他人可能也感兴趣 首先,调用一个函数,该函数将AT命令发送到ESP,以连接到ThingSpeak(数据记录服务器)。这在手动模式下工作良好,在尝试解析响应时也会连接,但它只解析返回的第一行。例如,串行监视器中的预期输出为: c AT+CIPSTART=“T
c
AT+CIPSTART=“TCP”,“api.thingspeak.com”,80
连接
好啊
连接到ThingSpeak!
其中,c
只是我键入的用于启动连接的命令字符
然而,实际答复如下:
c
AT+CIPSTART=“TCP”,“api.thingspeak.com”,80
无法连接到ThingSpeak!
连接
好啊
这意味着解析函数在收到响应之前结束。。。如下面的代码所示,当前指定了10秒超时。即使有20秒的超时,同样的事情也会发生,尽管手动执行时,响应大约在1秒内到达
为了测试解析函数,我尝试搜索“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!");
}
}
布尔waitForResponse(字符串目标,无符号长超时)
{
无符号长起始时间=毫秒();
字符串响应缓冲;
查尔查林;
//继续检查ESP响应,直到超时过期
while((毫秒()-startTime)<超时)
{
如果(特别是可用的())
{
responseBuffer+=尤其是read();
}
}
Serial.println(responseBuffer);
if(responseBuffer.endsWith(目标))
{
返回true;
}否则{
返回false;
}
}
void openCxn()
{
ESP.print(“AT+CIPSTART=\'TCP\',\'api.thingspeak.com\',80”);
延迟(500);
如果(等待响应(“80”,10000L))
{
Serial.println(“连接到ThingSpeak!”);
}否则{
Serial.println(“无法连接到ThingSpeak!”);
}
}
为什么它会在收到完整响应之前返回(在超时时间内)?这与endsWith()
函数有关吗
因此,您是否知道如何让它解析整个响应,而不仅仅是第一行
重申一下,我只对响应的结尾感兴趣(例如“OK”
或“OK\r\n”
)
知道它为什么在收到完整响应之前返回(在超时时间内)吗
是的,你的主要问题如下
if (ESP.available())
这使得waitForResponse函数在UART(或其他串行IO缓冲区)为空时返回—这不是您想要的。您需要从串行端口读取数据,直到收到以“\r\n”
结尾的行为止
这与endsWith()函数有关吗
是的,这是与ESP.available结合的另一个问题,因为您正试图将调制解调器的响应线末端与串行路径中发生的随机数据截断相匹配。如果你非常幸运,这将是线的边界,但很可能不是,你不应该依赖它
这是一个被称为的通用协议问题,适用于任何类型的异步串行通信。对于调制解调器通信,帧字符为\r
和\n
帮自己一个忙,实现一个readline
函数,该函数逐个读取字符,直到前一个字符是\r
,当前字符是\n
,然后返回到目前为止读取的所有内容
然后独家使用该功能1读取调制解调器响应数据。这既适用于中间结果代码,如CONNECT
,也适用于最终结果代码(如OK
等)。
然后,“解析”响应行就可以像
if (responseLine.equals("CONNECT\r\n")) ...
或
正如我所说,处理调制解调器输出的唯一正确方法是将输出分成完整的行,然后每次迭代一整行。
一,
唯一的例外是在解析AT+CMGS响应数据时。您的
if
在while
之后确实是错误的,因为您可能已经读回了更多内容,因此即使收到“ok”也不会以目标字符串结尾
您应该只测试responseBuffer是否以target结尾,并且仅当您在while
循环中收到新字符时才返回true,而不是之后。
超时后,只需返回false。很可能您收到的不是以“(
String::endsWith
)“80”结尾,而是以“80”结尾。非常感谢您的回复!我还是不明白为什么这么快就回来了<代码>“这会使waitForResponse函数在UART(或其他串行IO缓冲区)为空时返回。”如果缓冲区为空,它确实会离开循环,但循环会再次重复,因为它在超时循环内。为什么它不能捕获随后到达超时的下一个字符?@AntInvent该部分不正确。它将继续循环,直到超时。不过,endsWith
问题是真实的。如果你读了多于或少于一行(你几乎总是这样),那么你的逻辑就会失败。没错,我在开始写答案之前错过了这一点。您仍然应该将代码流转换为逐行解析所有内容,
if (isFinalResultCode(responseLine)) ...