从SIM900模块ESP32解析串行数据

发布于 2025-01-19 03:43:15 字数 4542 浏览 0 评论 0原文

所以最近我一直在考虑让我自己的手机没什么特别的,只是一个带有触摸屏和基本功能的基本手机,呼叫消息日历联系人列表以及连接到互联网并通过 API 调用提供天气信息的能力。 。 我用于 gsm 和 GPRS 通信的模块是流行的 sim900 模块。我可以沟通 我可以打电话 我可以做任何事情。但是陷入了一个可能(如果不是不可能克服)困难的障碍。您会看到 sim900 模块在收到呼叫时通过串行端口传输“RING”命令,然后是“+CLIP....(来电显示内容) ”。好的,我收到了,我正在分解它并接受命令,一切正常。但情况来了..我想读取剩余的电池容量(AT + CBC)和GSM信号强度(AT + CSQ)都很好我以固定的间隔(例如3秒)发送这2个命令电池信号10。但现在,当有电话打来时,它可能与尝试读取电池的传入响应重叠。假设我询问模块电池电量是多少。然后模块将通过发送“+CBC:(和电池电量)”进行响应,然后假设在同一时间我接到电话。然后串行端口上的所有数据都变得混乱并且没有任何工作。我的代码非常粗糙,而且解析部分肯定很糟糕,但我更担心解析不是问题。问题是传入数据冲突。有什么方法可以解决这个问题吗?或者有其他关于在哪里寻找以及如何解决问题的建议吗? 来自 gsm 的每个命令都由 0D0A 序列(CRLF)分隔,

下面是我正在做的示例代码

//for parsing
String incomStr;
String FirstStr;
String SecondStr;
String ThirdStr;
String FourthStr;
String FifthStr;
String SixthStr;
int strcount;
char incomChar;
boolean flagz = false;


//parsing
void getIncomingCommand() {
  if (Gsm.available()) {
    incomChar = Gsm.read();
    //check to see if 0D0A if yes split the string 
    if ((incomChar == 0x0D) | flagz) {
      flagz = true;
      if (incomChar == 0x0A) {
        switch (strcount) {
          case 0:
            FirstStr = incomStr;
            incomStr = "";
            strcount++;
            flagz = false;
            break;
          case 1:
            SecondStr = incomStr;
            incomStr = "";
            strcount++;
            flagz = false;
            break;
          case 2:
            ThirdStr = incomStr;
            incomStr = "";
            strcount++;
            flagz = false;
            break;
          case 3:
            FourthStr = incomStr;
            incomStr = "";
            strcount++;
            flagz = false;
            break;
          case 4:
            FifthStr = incomStr;
            incomStr = "";
            strcount++;
            flagz = false;
            break;
          case 5:
            SixthStr = incomStr;
            incomStr = "";
            strcount++;
            flagz = false;
            break;
          default:
            strcount++;
            flagz = false;
            incomStr = "";
        }
      }
    } else {
      incomStr += incomChar;
    }
  }
}


void clearIncomingCommand() {
  FirstStr = "";
  SecondStr = "";
  ThirdStr = "";
  FourthStr = "";
  FifthStr = "";
  SixthStr = "";
  strcount = 0;
}


int getSignalLvl() {
  char tempchar;
  String tempstr;
  Gsm.print("AT+CSQ");
  Gsm.write(0x0D);
  Gsm.write(0x0A);
  delay(180);
  while (Gsm.available()) {
    tempchar = Gsm.read();
    tempstr += tempchar;
  }
  return tempstr.substring(16, tempstr.indexOf(",")).toInt();
}

String getTime() {
  char tempchar;
  String tempstr;
  Gsm.print("AT+CCLK?");
  Gsm.write(0x0D);
  Gsm.write(0x0A);
  delay(180);
  while (Gsm.available()) {
    tempchar = Gsm.read();
    tempstr += tempchar;
  }
  return tempstr.substring(tempstr.indexOf(",") + 1, tempstr.lastIndexOf(":"));
}

void setup() {
  //start serial port
  Serial.begin(115200);
  //start the gsm port
  Gsm.begin(9600, SERIAL_8N1, 32, 33);
  strcount = 0;
  updateTime(getTime());
  delay(200);
  updateSignal(getSignalLvl());
}

void loop() {
  //stuff inside here will only be called / run only every X amount of time
  // X = SECONDS/1000;
  if ((millis() - lastupdate) >= 60000) {
    updateTime(getTime());
    lastupdate = millis();
  }



  getIncomingCommand();
  if (SecondStr == "RING" & FourthStr.substring(0, 5) == "+CLIP") {
    Serial.print("SomeOne is calling!! Number: ");
    Serial.println(FourthStr.substring(8, 21));
      Serial.println(phoneNums[i]);
      Serial.println(FourthStr.substring(8, 21));
      callerPhone = FourthStr.substring(8, 21);
      clearIncomingCommand();
    //important change state only once!
    if (!change_state) {
      came_from = state ;
      change_state = 1;
    }
    Serial.print("coming from: ");
    Serial.println(came_from);
    state = 4;
    flag = 0;
  }
  else if (SecondStr == "NO CARRIER") {
    Serial.println("CALL ENDED");
    clearIncomingCommand();
    if (state == 3) {
      state = 5;
      flag = 0;
    } else if (state == 4) {
      state = came_from;
      flag = 0;
    }
    change_state = 0;
  }
  else if (SecondStr == "MO RING") {
    Serial.println("CALLING...");
    clearIncomingCommand();

  }
  else if (SecondStr == "MO CONNECTED") {
    Serial.println("CALL CONNECTED");
    clearIncomingCommand();
    if (state == 2) {
      state = 3;
      flag = 0;
    }
  } else if (FourthStr == "OK" | ThirdStr == "OK") {
    Serial.println("Recieved ok clearing buffers");
    clearIncomingCommand();

  }


}

So lately I've been messing around with the idea of making my own cellphone nothing spectacular, just a basic one with touchscreen and basic functions call message calendar contacts list and the ability to connect to the internet and provide weather information via an api call..
The module Im using for gsm and GPRS communications is the popular sim900 module. I can communicate I can make calls I can do everything. But in stuck on a maybe (if not impossible to overcome) difficult roadblock.. You see sim900 module when receives a call transmits through the serial port the "RING" command followed by the "+CLIP.... (caller Id stuff)". OK I'm receiving that and I am breaking it down and accepting the command and all fine it works. But here comes the situation.. I want to read the battery capacity that is left (AT+CBC) and the gsm signal strength (AT+CSQ) all fine I'm sending those 2 commands at a fixed interval of like 3 seconds for the signal 10 for the battery. But now when a call comes it might overlap with the incoming response from trying to read the battery.. Let's say that I asked the module what is the battery level. Then the module will respond by sending "+CBC: (and battery level)" then let's say at the same exact time I receive a call.. Then all the data on the serial port just gets messed up and nothing is working.. My code is pretty rough and definitely the parsing section is awful but I'm more concerned that the parsing is not the problem. And the problem is the conflicting incoming data.. Is there any way of solving this problem? Or any other advice of where to look and how to approach the problem?
Every command from the gsm is delimited by the 0D0A sequence (CRLF)

Bellow is an example code from what i am doing

//for parsing
String incomStr;
String FirstStr;
String SecondStr;
String ThirdStr;
String FourthStr;
String FifthStr;
String SixthStr;
int strcount;
char incomChar;
boolean flagz = false;


//parsing
void getIncomingCommand() {
  if (Gsm.available()) {
    incomChar = Gsm.read();
    //check to see if 0D0A if yes split the string 
    if ((incomChar == 0x0D) | flagz) {
      flagz = true;
      if (incomChar == 0x0A) {
        switch (strcount) {
          case 0:
            FirstStr = incomStr;
            incomStr = "";
            strcount++;
            flagz = false;
            break;
          case 1:
            SecondStr = incomStr;
            incomStr = "";
            strcount++;
            flagz = false;
            break;
          case 2:
            ThirdStr = incomStr;
            incomStr = "";
            strcount++;
            flagz = false;
            break;
          case 3:
            FourthStr = incomStr;
            incomStr = "";
            strcount++;
            flagz = false;
            break;
          case 4:
            FifthStr = incomStr;
            incomStr = "";
            strcount++;
            flagz = false;
            break;
          case 5:
            SixthStr = incomStr;
            incomStr = "";
            strcount++;
            flagz = false;
            break;
          default:
            strcount++;
            flagz = false;
            incomStr = "";
        }
      }
    } else {
      incomStr += incomChar;
    }
  }
}


void clearIncomingCommand() {
  FirstStr = "";
  SecondStr = "";
  ThirdStr = "";
  FourthStr = "";
  FifthStr = "";
  SixthStr = "";
  strcount = 0;
}


int getSignalLvl() {
  char tempchar;
  String tempstr;
  Gsm.print("AT+CSQ");
  Gsm.write(0x0D);
  Gsm.write(0x0A);
  delay(180);
  while (Gsm.available()) {
    tempchar = Gsm.read();
    tempstr += tempchar;
  }
  return tempstr.substring(16, tempstr.indexOf(",")).toInt();
}

String getTime() {
  char tempchar;
  String tempstr;
  Gsm.print("AT+CCLK?");
  Gsm.write(0x0D);
  Gsm.write(0x0A);
  delay(180);
  while (Gsm.available()) {
    tempchar = Gsm.read();
    tempstr += tempchar;
  }
  return tempstr.substring(tempstr.indexOf(",") + 1, tempstr.lastIndexOf(":"));
}

void setup() {
  //start serial port
  Serial.begin(115200);
  //start the gsm port
  Gsm.begin(9600, SERIAL_8N1, 32, 33);
  strcount = 0;
  updateTime(getTime());
  delay(200);
  updateSignal(getSignalLvl());
}

void loop() {
  //stuff inside here will only be called / run only every X amount of time
  // X = SECONDS/1000;
  if ((millis() - lastupdate) >= 60000) {
    updateTime(getTime());
    lastupdate = millis();
  }



  getIncomingCommand();
  if (SecondStr == "RING" & FourthStr.substring(0, 5) == "+CLIP") {
    Serial.print("SomeOne is calling!! Number: ");
    Serial.println(FourthStr.substring(8, 21));
      Serial.println(phoneNums[i]);
      Serial.println(FourthStr.substring(8, 21));
      callerPhone = FourthStr.substring(8, 21);
      clearIncomingCommand();
    //important change state only once!
    if (!change_state) {
      came_from = state ;
      change_state = 1;
    }
    Serial.print("coming from: ");
    Serial.println(came_from);
    state = 4;
    flag = 0;
  }
  else if (SecondStr == "NO CARRIER") {
    Serial.println("CALL ENDED");
    clearIncomingCommand();
    if (state == 3) {
      state = 5;
      flag = 0;
    } else if (state == 4) {
      state = came_from;
      flag = 0;
    }
    change_state = 0;
  }
  else if (SecondStr == "MO RING") {
    Serial.println("CALLING...");
    clearIncomingCommand();

  }
  else if (SecondStr == "MO CONNECTED") {
    Serial.println("CALL CONNECTED");
    clearIncomingCommand();
    if (state == 2) {
      state = 3;
      flag = 0;
    }
  } else if (FourthStr == "OK" | ThirdStr == "OK") {
    Serial.println("Recieved ok clearing buffers");
    clearIncomingCommand();

  }


}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文