AT命令响应(理解Arduino上代码执行的顺序)

时间:2016-06-22 18:48:31

标签: c arduino at-command esp8266 ends-with

我正在从Arduino Uno / Nano(ATmega328)向ESP8266发送AT命令并尝试解析收到的字符串的结尾,以确定ESP如何反应以及它是否成功(以及它是否已准备好接收另一个命令)。我知道在此之前已经讨论过解析AT命令响应:Get AT command response

但我有一个特定的问题,那里的其他人可能也会感兴趣...

首先,调用一个函数,它将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")。

2 个答案:

答案 0 :(得分:0)

  

知道为什么它会在收到完整响应之前返回(在超时期限内)?

是的,您的主要问题是以下

if (ESP.available())

这使得只要UART(或其他一些串行IO缓冲区)为空,waitForResponse函数就会返回 - 这不是你想要的。你想要的是从串口读取,直到你收到以"\r\n"终止的行。

  

是否与endsWith()函数有关?

是的,这是与ESP.available结合的另一个问题,因为您试图将来自调制解调器的响应行的末尾与串行路径中发生的随机数据斩波相匹配。如果你非常幸运,这将是在线边界,但很可能不是,你不应该依赖它。

这是一个称为framing的通用协议问题,适用于任何类型的异步串行通信。对于调制解调器通信,框架字符为\r\n

帮自己一个忙,并实现一个一个字符读取的readline函数,直到前一个字符为\r且当前字符为\n,然后返回它读取的所有内容远。

然后使用该功能专门 1 来读取调制解调器响应数据。这既适用于中间结果代码,例如CONNECT,也适用于最终结果代码(例如OK等)。 &#34;解析&#34;然后,响应行可以像

一样简单
if (responseLine.equals("CONNECT\r\n")) ...

if (isFinalResultCode(responseLine)) ...

正如我所说before处理调制解调器输出的唯一正确方法是将输出分成完整的行,然后迭代一整行。

1 唯一的例外是解析AT + CMGS响应数据。

答案 1 :(得分:0)

你是否在一段时间之后确实是错的因为你可能已经阅读了更多的东西,因此即使收到确认,你也不会以目标字符串结束。

你应该只测试responseBuffer是否以目标结束并返回true只有当你在while循环中而不是之后收到一个新的Char时。 超时后,只返回false。