1

我有 Arduino UNO 和一个 Sim800L 模块,我知道读取串行的方式,就像这个问题一样,但是当我执行这个功能时:

    String GetRegData()
    {
      Serial.println("Get nearby antenna info ...");
      SIM800L.print("AT+CNETSCAN=1\r");
      delay(1000);

      SIM800L.print("AT+CNETSCAN\r"); 
      delay(1000);

      String buffer2;

      while (SIM800L.available())
       {
          char c = SIM800L.read();
          Serial.print(c);
          buffer2.concat(c);
          delay(10);
       }
       //Serial.println();
       return buffer2;
    }

输出是:

AT+CMGF=1

OK
AT+CNMI=2,2,0,0,0

OK
AT+CNETSCAN=1

OK
AT+CNETSCAN

Operator:"XXXX",MCC:XXX,MNC:XX,Rxlev:XX,Cellid:XX,Arfcn:XX,Lac:q5er32xlAair32xlAacrseifcca,Nvdc00

这个 AT 命令(AT+CNETSCAN)应该扫描所有附近的天线并在多行中打印一些信息(根据数据表),当我在这个设备(SIM800L)上手动执行这个命令时,我得到多行这样的:

Operator:"XXXX",MCC:XXX,MNC:XX,Rxlev:XX,Cellid:XX,Arfcn:XX,Lac:XX,Bsic:XX
Operator:"XXXX",MCC:XXX,MNC:XX,Rxlev:XX,Cellid:XX,Arfcn:XX,Lac:XX,Bsic:XX
Operator:"XXXX",MCC:XXX,MNC:XX,Rxlev:XX,Cellid:XX,Arfcn:XX,Lac:XX,Bsic:XX
OK

但是我不知道当我以编程方式执行此操作时会发生什么,它搞砸了,我尝试更改波特率并更改接收方法并逐字符读取字符,我确实在接收之间设置了延迟,我尝试这样做iffor代替while 但没运气。

我猜在接收每一行之间会有延迟,它会破坏串行可用性,但我不知道该怎么做!任何帮助,将不胜感激。

顺便说一下,我的设置功能:

void setup() {
  SIM800L.begin(9600);
  Serial.begin(9600); 
  delay(3000);

  SIM800L.print("AT+CMGF=1\r"); 
  delay(100);

  SIM800L.print("AT+CNMI=2,2,0,0,0\r");
  delay(100);
  GetRegData();

  delay(1000);
}

Ps:整个东西(Arduino + Sim800L)工作正常,没有错误,Simcard已解锁,它可以发送接收短信和电话等。

4

3 回答 3

0

两个提示:

  • 摆脱接收函数中的所有延迟(),它会停止处理每个字符 10 毫秒,从长远来看,这可能会导致串行缓冲区溢出
  • 摆脱 String 类,读入一个足够大的 char 缓冲区以接收最大的预期消息。示例可以在 stackexchange 上找到。

如果您执行两种方式的 com,则 serial.available() 很方便,但您需要自己检查终端终止符或其他外部信号。

于 2020-04-08T16:02:54.880 回答
0

通过花费数小时思考整个过程,我想出了一个主意:

在串行端口停留 10 秒,然后得到它吐出的东西!NO 串口断线 NOwhile (SIM800L.available() != 0)

elapsedMillis是库,这是代码:

String buffer2;

elapsedMillis timeElapsed;
unsigned int interval = 10000; 

while(timeElapsed < interval){
    if (SIM800L.available() != 0){ // for ignoring the NULLs
        char c = SIM800L.read();
        Serial.print(c);
        buffer2.concat(c);
      }
}

虽然这个过程有一些亮点:

1-旧循环没有得到整个输出的主要原因是,SIM800L.available()在多线接收期间变成了零!

2-String数据类型或SIM800L.read();不要做错任何事情,理论上它们没有读取设备输出(如64字节)字符的限制,它们全部读取

3- 有时电子设备表现出奇怪的特殊 Sim800L 又旧又便宜!

4- 如果您要通过 SMS 发送此数据(网络天线扫描),请注意 SMS 最大字符限制,并考虑到服务提供商将向您收取大约每发送 150 个字符的费用!\r\n并从响应中删除字符,并AT+CSMP=17,167,0,0在 SIM800L 上发送短信之前运行,否则它将发送一条空白短信!

5- Sim800L数据表说它在端口115200上工作得最好, 但是对于这个设备来说太快了!将其波特率设置为9600

于 2020-04-09T07:11:48.683 回答
0

根据 OP 的回答,问题在于serial.available()返回 0 并使循环过早结束。

这可能是因为两个连续serial.read()调用之间的延迟太低,并且等待一些侧面场景(例如更多行中出现的 AT 响应)是不够的。

增加延迟是错误的,因为响应是逐个字符读取的,并且该更改会影响总时间。可以做的是在字符间总延迟后退出循环。以下示例200ms使用了 的值:

#define MAX_DELAY_MS  200
#define LOOP_DELAY_MS 10

String GetRegData()
{
  int intercharTime = 0;

  Serial.println("Get nearby antenna info ...");
  SIM800L.print("AT+CNETSCAN=1\r");
  delay(1000);

  SIM800L.print("AT+CNETSCAN\r"); 
  delay(1000);

  String buffer2;

  while (  intercharTime < MAX_DELAY_MS  )
   {
      if( SIM800L.available() )
      {
          int c = SIM800L.read();

          /* read() return -1 on fail. Make sure it read something before using c */
          if( c != -1 )
          {
              Serial.print( (char)c );
              buffer2.concat( (char)c );

              /* Something received: reset intercharTime */
              intercharTime = 0;
          }
      }
      else
      {
          intercharTime += LOOP_DELAY_MS;
      }

      delay(LOOP_DELAY_MS);
   }

   //Serial.println();
   return buffer2;
}

变化:

  • intercharTime检查退出循环。每次serial.available()返回 0 时增加。每次接收到字符时重置。这样我们在MAX_DELAY_MS几毫秒后退出循环。
  • read() 返回一个整数,所以我将它放在一个整数变量上,并char在需要时将其转换为。此外,它在失败时返回 -1。在处理可能无效的数据之前检查返回值总是更好。
  • 我还10ms用定义代替了延迟。通过这种方式,很容易与几对情侣一起玩,LOOP_DELAY_MS以便MAX_DELAY_MS找到最合适的人。
于 2020-04-09T09:51:36.763 回答