基于Arduino连接SIM800l的GPRS通信实现

分享,记录 2017-01-18 14 条评论 访问: 49,341 次

最近,我希望利用arduino实现基于互联网的通信,基于GPRS而不是WIFI等,场所受限制的通信方式,故我选择SIM800l这款小型的GSM/GPRS模块,该模块可以实现通过AT命令进行打电话,发短信,并且可以实现tcp连接,也可以基于GPRS的互联网的访问。本文实现的就是sim800l基于gprs技术的互联网访问。最终效果就是从某个服务器上获取特定格式的命令信息。

附效果图

arduino-with-sim800l-get-data-via-GPRS

完整程序:(延时真的非常重要,否则会存在无法获取数据的现象)

#include <SoftwareSerial.h>
#include <MsTimer2.h>

//SIM800 TX is connected to Arduino D8
#define SIM800_TX_PIN 8 //D8连接sim800l的tx
//SIM800 RX is connected to Arduino D9
#define SIM800_RX_PIN 9 //D9连接sim800l的rx
SoftwareSerial mySerial(SIM800_TX_PIN,SIM800_RX_PIN);//定义虚拟串口
void setup(){
    delay(10000);//单片机和sim800l上电之后,这个延时是用来等待sim800l获取信号(获取到信号之后的状态是3s闪一下)
    Serial.begin(9600);//初始化默认串口
    SIM800Init();//初始化sim800l,并将其置于数据连接打开的状态
    bitSet(DDRB,5);//位操作,将D5口置高
    MsTimer2::set(1000,getData_ISR);//定时器中断1s一次,即每两秒获取一次数据
    MsTimer2::start();//开启定时器
}
char cmd[10]={0};//获取到的数据,长度为10个char
char sign=0;//步骤标志位,这样可以少加一个定时器
void loop(){//循环函数
  delay(500);
  char i=0;
  for(i=0;i<=9;i++)Serial.write(cmd[i]);//输出获取到的数据
  if(cmd[0]=='1'){
    Serial.println("TURE");//如果第一位为’1‘即认定
    if(cmd[1]=='1')bitSet(PINB,5);//如果第二位为’1‘即认定执行翻转电平的操作
    }else{
    Serial.println("FALSE");//否则数据无效
    }
}
void SIM800Init(){
  mySerial.begin(9600);//初始化串口波特率
  delay(1000);//适当延时
  Serial.println("Setup Complete!");
  mySerial.write("AT\r");//发送AT返回OK
  while(mySerial.available())Serial.write(mySerial.read());//接收返回的数据并打印到串口监视器上
  mySerial.write("AT+SAPBR=3,1,\"APN\",\"CMNET\"\r");//注册
  delay(500);
  while(mySerial.available())Serial.write(mySerial.read());
  mySerial.write("AT+SAPBR=3,1,\"PHONENUM\",\"15100000000\"\r");//注册
  delay(500);
  while(mySerial.available())Serial.write(mySerial.read());
  mySerial.write("AT+SAPBR=4,1\r");
  delay(500);
  while(mySerial.available())Serial.write(mySerial.read());
  mySerial.write("AT+SAPBR=1,1\r");//打开承载此时sim800l上的灯快闪
  delay(1000);
  while(mySerial.available())Serial.write(mySerial.read());
  mySerial.write("AT+SAPBR=2,1\r");
  delay(1000);
  while(mySerial.available())Serial.write(mySerial.read());
  mySerial.write("AT+HTTPINIT\r");//初始化http协议
  delay(1000);
  while(mySerial.available())Serial.write(mySerial.read());
  mySerial.write("AT+HTTPPARA=\"CID\",\"1\"\r");
  delay(500);
  while(mySerial.available())Serial.write(mySerial.read());
  mySerial.write("AT+HTTPPARA=\"URL\",\"http://test.umview.com/\"\r");//连接到服务器
  delay(500);
  while(mySerial.available())Serial.write(mySerial.read());
  mySerial.write("AT+HTTPACTION=0\r");//请求
  delay(1000);
  while(mySerial.available())mySerial.read();//此时请求成功的话会获取到’0,200,20‘200是服务器的返回码代表请求成功,获取到的长度
  mySerial.write("AT+HTTPREAD=1,14\r");//开始获取长度为14
  delay(1000);
  while(mySerial.available())Serial.write(mySerial.read());//串口输出
}

void getData(){//获取数据函数
  char cnt=0;
while(mySerial.available()){
    char c=mySerial.read();
    if(c=='#'){//识别’#‘
    for(cnt=0;cnt<=9;cnt++)cmd[cnt]=mySerial.read();//保存数据到cmd数组,并识别到’#‘为结束
    }
  mySerial.read();//读取剩下的字符
  }
}
void requestDataStep1(){
  mySerial.write("AT+HTTPACTION=0\r");//请求数据
}
void requestDataStep2(){
    while(mySerial.available())mySerial.read();
    mySerial.write("AT+HTTPREAD=1,14\r");//请求特定字长的数据
}
void getData_ISR(){ //定时器中断,1s执行一次
  if(sign==0)requestDataStep1(),sign++;//第一步执行 requestDataStep1
  else if(sign==1)requestDataStep2(),sign++;//第二步执行 requestDataStep2
  else getData(),sign=0,Serial.println("getData");//第三步执行 getData 获取数据
}

服务器上的数据格式是:##1101012345#
注:第一个#无法获取到,有效数据为#之间的部分,’1‘为数据有效标志位。
至此,我们成功利用arduino通过sim800l基于gprs获取到互联网上的数据,并成功控制了一个LED。
优点:利用中断节约了大量cpu时间,这些时间本该用于延时获取数据时的等待。基于移动互联网,不过多地受位置限制,有移动信号就可以。
缺点:此sim800l模块,对电压要求较高,低电压会报警重启。对于串口的缓存区,必须要即时清空,否则会影响有效数据的接收,出现乱码,设置有效位’1‘可能会解决此类问题,可能需要设置很多有效位。由于存在较多的while用于清空串口的buff,存在程序卡死在while中的现象,但不多。通电时间长了,sim800l会存在轻微发热的情况。还有服务器上的数据第一个字节无法获取,问题无法解决。
可是,对于用sim800l上传数据和连接tcp服务器的功能并没有开发出来,需要日后继续改进。
附源代码:https://github.com/umview/Arduino


除非注明,嗯VIEW文章均为原创,转载请以链接形式标明本文地址
本文地址:https://www.umview.com/arduino-with-sim800l-get-data-via-GPRS

本文由 nash.zhao 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

14 条评论

  1. 豆汤
    豆汤

    您好,请问这里可以用4G的电话卡吗?

    1. 11
      11

      可以

  2. 高

    您好,我按照你的代码,执行后9600串口上一直显示FALSE和getDate为什么呢?

    1. nash.zhao
      nash.zhao

      可能是因为,请求服务器数据失败了,或者是传输错码了,建议换个网站!

  3. Richard
    Richard

    用SoftwareSerial连接SIM800这方法好,留着标准serial做串口监视用。一接上TX,RX,V-ref, GND就行了,可发AT命令了。

    1. nash.zhao
      nash.zhao

      用标准口的话以后还是要折腾,不如留着调试用。哈。

  4. wuxian
    wuxian

    大神,本人做移动端软件开发,没接触过硬件,有问题请教,请加我微信:wuxian,有谢!

  5. 小白
    小白

    求连线,arduino UNO 和SIM800C,QQ1564346140事后有心意,谢谢

    1. nash.zhao
      nash.zhao

      大佬,,我已经加过你了:)

  6. Avenger
    Avenger

    求教,我也不会怎么连线,SIM800和uno r3,谢谢,QQ769814089,事成有心意

  7. 空白晓色
    空白晓色

    本人小白,想要给我外婆弄个报警器,可以第一时间让子女知道,我买了arduino 101 和sim800,可是后来我蒙蔽了,不知道怎么连线,!!~~~~

    大神,求帮助。

    本人之前就是个普通的程序员,没接触过硬件

    1. nash.zhao
      nash.zhao

      私聊一下吧。

      1. zhqy
        zhqy

        我也刚买了个SIM800,同样不懂连线,模块也没相关资料,同求帮助

        1. gao
          gao

          您好,我看你用的也是SIM800,您的代码好用了吗?

添加新评论