一文教会你嵌入式网络模块的联网操作

作者:良知犹存

转载授权以及围观:欢迎添加微信公众号:Conscience_Remains

总述

    现在物联网的概念越来越突出,软件云端小米IOT平台、阿里物联网云等等,嵌入式百度手环开源很久了,此外网上关于ESP8266接入网关进行远程控制的源码不计其数。

   物联网嵌入式端开发使用中都是各大主流网络模块,其中无线方式通信方式区分的话,主要分为两类:一类是Zigbee、WiFi、蓝牙、Z-wave等短距离通信技术;另一类是LPWAN(low-powerWide-AreaNetwork,低功耗广域网),即广域网通信技术。

   至于几种通信模块使用的技术区别,改天可以写一篇文章进行详细介绍。不过 今天我来介绍一下,我使用过的一款2G网络模块,在车载行驶中使用,在很恶劣的情况下,依旧可以保证网络快速链接。因为现在的网络模块都是差不多的,尤其是IOT、LORA以及2G 3G 4G这些通过基站进行组网的模块。

有兴趣的朋友可以看看百度手环的开源资料,后台回复 find me 加我好友进行分享。

一、概念介绍

2G:第二代移动通信技术加入更多的多址技术,包括TDMA和CDMA,同时2G是数字通信,因此在抗干扰能力上大大增强。第二代移动通信可以说对接下来的3G和4G奠定了基础,比如分组域的引入,和对空中接口的兼容性改造,使得手机不再只有语音、短信这样单一的业务,还可以更有效率的连入互联网(电路域也可以提供internet业务,只是相对来说分组域更适合internet业务)。2G主要的制式也是两个,分别是来自欧洲ETSI组织的GSM(GPRS/EDGE)和来自美洲以高通公司为主力的TIA组织的CDMA IS95/CDMA2000 1x。

    看到这里大家就有疑问了,上面巴拉巴拉一堆介绍中,2G网络看上去都是很落后的了,毕竟现在5G都出了。2G都没人用了,有什么好讲的。那我这里就给2G正个名。

    现在网络通信技术发展的很快,手机等终端对最新通信技术的支持也是很及时,但是也是在手机这块。要知道手机现在的售价是很高的,在长时间的快速更新换代中,消费者也逐渐接受了这些技术指标以及消费价格。但是在一些工业领域,物联网产品中,只要很小的带宽,网络覆盖率广,流量费用足够低,甚至需要低功耗的模块。IOT LORA就是现在物联网选择比较多的模块,但是IOT依旧 也有自己的缺点。

    “NB-IOT实际使用没有理论宣传那么好,NB-IOT,功耗低、传输距离远、系统容量大,这些都是耳熟能详的好处了。但是,功耗低:在大部分场景下,NB并不比2G功耗低多少;传输距离远:现在2G网络全覆盖,NB-IOT还在铺网阶段,体现不出来优势;系统容量大:当前物联网产品远远没有把2G网络占满,更体现不出来NB能容纳更多设备的优势了。价格贵:NB-IOT模块比2G模块贵3-4倍,算上运营商补贴还是要贵不少。”

    而2G由于通信模块成本较低,不到4G模块的三分之一。市面上的共享单车定位和开锁、POS刷卡支付也采用2G网络连接。所以2G网络现阶段应用还是比较广的,所以我们之前也是采用了2G网络模块进行的开发。

二、模块情况

    2G模块比较有名就是上海移远公司的M26模块,出来时间比较长了,但是M26只有GPRS的功能。

所以我们选择了中移的M6313模块GPRS和GNSS二合一模块。相关的资料现在也是很多了,一般我们用到是AT命令使用手册,通信流程示例手册。通信手册我开发的时候还没有,现在中移出了,挺开心的,又解决了开发者的一些难题。

首先我们开发使用是也是云,嵌入式端没有使用现在比较火的MQTT或者CoAP这些协议,而是直接使用TCP进行端口链接到服务器。

因为M6313模块的功能和M26很像,所以这个TCP链接过程是可以沿用的。

三、联网状态机分析


 下面是当初开发时候的写一个联网状态机,最后基本达到在CSQ在12~24时候,联网时候可以最快达到4~5秒。

这个状态机可以实现联网,设置模块自动心跳、切换IP等功能。具体的解释也都在代码里面展示了。

static void TCP_Conncect(const char* ipaddr, const char* ipport)

{

  char* p = NULL;

  p = (char*) malloc(100);

  if(NULL == p)

  {

    LOG("malloc p error!\r\n");

  }

  else

  {

    memset(p, 0, 100);

    sprintf(p, "AT+QIOPEN=\"TCP\",\"%s\",%s",ipaddr, ipport);

    mdm_send_cmd_noack((u8*)p);

    LOG("%s\r\n", p); //DEBUG

  }

  free(p); 

}

/*

  ******************************************************************

  * @brief  进行IP修改时候IP正确性标志清零

  * @author  Conqueror(征服者)

  * @version V1.0

  * @date    2019-6-10

  ******************************************************************

*/

u8 IsIPvalid = 0;

static void ChangeIP(void)

{

  IsIPvalid = 0;

  dprintf("Clear IsIPvalid!\r\n");

}

/*

  ******************************************************************

  * @brief  timer.c进行调用此函数进行判断IP是否正常通讯

  * @author  Conqueror(征服者)

  * @version V1.0

  * @date    2019-6-17

  ******************************************************************

*/

TimTypeDef SecIPTimeManage;

void SecIPManageTimer(void)

{

  if(SecIPTimeManage.stat == TON)

  {

  (SecIPTimeManage.cunt < SecIPTimeManage.des)?(SecIPTimeManage.cunt++):\

  (TimerManageInit(&SecIPTimeManage,TOFF,0),IsIPvalid=0);

  } 

}

/*

  ******************************************************************

  * @brief  IP为正确可用的,可以进行写进FLASH

  * @author  Conqueror(征服者)

  * @version V1.0

  * @date    2019-6-17

  ******************************************************************

*/

void IPValid(void)

{

  if(devParam.secondTcp.addr[0] !=0)

  {

    IsIPvalid=1;

    TimerManageInit(&SecIPTimeManage,TOFF,0);

    LOG("IP Valid !\r\n");

  }

}

/*

  ******************************************************************

  * @brief  用于第一次连接新的IP地址的时候进行发送测试

  * @author  Conqueror(征服者)

  * @version V1.0

  * @date    2019-6-17

  ******************************************************************

*/

static void TestTCP(void)

{

  if(cntMdm == 1 && devParam.secondTcp.addr[0] !=0)

  {

      M6313SendTestData();/*确认IP情况*/

      TimerManageInit(&SecIPTimeManage,TON,2000);/*20s判断*/

  }

}

/*

  ******************************************************************

  * @brief  判断IP是否正确,不正确直接清零

  * @author  Conqueror(征服者)

  * @version V1.0

  * @date    2019-6-17

  ******************************************************************

*/

void IsTCPIPVaild(void)

{

  if(gCnt.mdmTotalErr > 3&&mdmInfo.signalIntensity > 10)

  {

    memset(&devParam.secondTcp,0x00,sizeof(devParam.secondTcp));/*只要新的进入则清除之前的数据*/

  }

  if(IsIPvalid == 0 && SecIPTimeManage.stat == TOFF && cntMdm==1\

                    && econdTcp.addr[0] !=0)

  {

    LOG("IPInvalid !\r\n");

    mdmFSMPWRRSTInit(); /*断电重启*/   

    memset(&devParam.secondTcp,0x00,sizeof(devParam.secondTcp));/*只要新的进入则清除之前的数据*/

  }

}

void mdmFSMPWRRSTInit(void)

{

  MDM_STA = MDM_EXE_PWRRST_ACT;          /*设置mdmComFSM状态*/ 

  TBoxInfoType.userInfo.bit.cntMdm = 0;  /*网络默认断开*/ 

  SysFlag.mdmFSMRunSta = 1;              /*启动MDM_FSM,TCP错误处理程序将在一定时间内不执行*/ 

  gtimer.mdmFSMRun = gtimer.timer;      /*MDM_FSM处理,开始时刻*/ 

  dprintf("-mdmFSM_PWRRST_Init\r\n");   

}

void STOP_MDM_FSM(void)

{

  SysFlag.mdmFSMRunSta = 0; /*MDM_FSM强制结束*/

  gtimer.mdmFSMRun = 0;

}

void mdmComFSM(void)

{

  static u8 iTimes = 0;      /*发AT CMD次数*/

  static u8 mdmPwrOnCnt = 0; /*MDM开机次数*/

  if(MDM_STA != MDM_IDLE_STA) /*FSM运行中,刷新*/

  {

    refreshWorkTimer();

  }


  switch(MDM_STA)

  {

    case MDM_IDLE_STA: 

      break;

/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------*/   

    /*模块断电复位*/

    case MDM_EXE_PWRRST_ACT:

      LOG("*%d<-:MDM_PWR_RST[T:%d]\r\n", MDM_EXE_PWROFF_ACT, gtimer.timer);

      MDM_PWR_EN_L;

      gtimer.mdmFSMTimerout = 0;

      MDM_STA = MDM_WAIT_PWRRST_RES;         

      break;

    case MDM_WAIT_PWRRST_RES:

      if(gtimer.mdmFSMTimerout > 2000) /*超过10秒*/

      {

        gtimer.mdmFSMTimerout = 0;

        MDM_PWR_EN_H;

        LOG("MDM_PWR_EN_H!\r\n");

        MDM_STA = MDM_EXE_PWRON_ACT;

        LOG("MDM_PWR_RST Finish!\r\n");

      }

      break; 


    /*模块关机*/   

    case MDM_EXE_PWROFF_ACT: /*模块关机:开机状态模块的PWRKEY拉低1s关机*/

      LOG("\r\n*Step:%d,MDM_EXE_PWROFF_ACT,time:%d\r\n", MDM_EXE_PWROFF_ACT, gtimer.timer);

      MDM_PWRKEY_EN_H;

      gtimer.mdmFSMTimerout = 0;

      MDM_STA = MDM_WAIT_PWROFF_RES;         

      break;

    case MDM_WAIT_PWROFF_RES:

      if(gtimer.mdmFSMTimerout > 200) /*超过1秒*/

      {

        gtimer.mdmFSMTimerout = 0;

        MDM_PWRKEY_EN_L;  /*m6313的PWRKEY处产生高电平*/                 

        MDM_STA = MDM_WAIT_PWROFF_DELAY;

        LOG("MDM_PWRKEY_EN_L,PWROFF_time:%d\r\n", gtimer.timer);

      }

      break;


    case MDM_WAIT_PWROFF_DELAY:

      if(gtimer.mdmFSMTimerout > 2400) /*12秒等待,模块关机完成*/

      {

        LOG("MDM_POWER_OFF finish\r\n");

        MDM_STA = MDM_EXE_PWRON_ACT;                 

      } 

      break;


    /*模块开机*/ 

    case MDM_EXE_PWRON_ACT: /*模块开机:在关机状态模块的PWRKEY拉低2s开机*/

      LOG("\r\n*Step:%d,MDM_EXE_PWRON_ACT,time:%d\r\n", MDM_EXE_PWRON_ACT,gtimer.timer);

      M6313ComInit();

      MDM_PWRKEY_EN_H;

      gtimer.mdmFSMTimerout = 0;

      MDM_STA = MDM_WAIT_PWRON_RES;         

      break;

    case MDM_WAIT_PWRON_RES:

      if(gtimer.mdmFSMTimerout > 400) /*超过2秒*/

      {

        MDM_PWRKEY_EN_L; /*PWRKEY开机流程结束*/

        mdmPwrOnCnt++;

        LOG("MDM_POWER_ON,,time:%d\r\n", gtimer.timer); 

        MDM_STA = MDM_TX_AT_CMD;                   

      }   

      break;   

    /*检查MDM通信*/   

    case MDM_TX_AT_CMD:

      LOG("\r\n*Step:%d,AT\r\n", MDM_TX_AT_CMD);//step 1

      LOG("AT-%d-\r\n", iTimes);

      mdm_send_cmd_noack((u8*)"AT");

      iTimes++;     

      gtimer.mdmFSMTimerout = 0;

      MDM_STA = MDM_WAIT_AT_RES;

      break;

    case MDM_WAIT_AT_RES:

      if(!mdm_check_str((u8*)"OK")) /*查询到OK*/

      {

        LOG("AT-OK-%d-\r\n", iTimes);

        if(mdmPwrOnCnt > 0)

        {

          MDM_STA = MDM_WAIT_GSM_READY; /*模块开机,需要一定时间,等待GSM注册成功*/

          gtimer.mdmFSMTimerout = 0;

        }

        else{

          MDM_STA = MDM_START_INIT;   

        }

      }

      else if(gtimer.mdmFSMTimerout > 400) /*本次等待2秒超时*/

      {

        if(iTimes < EXE_AT_TIMES)

        {

          MDM_STA = MDM_TX_AT_CMD; /*继续发送AT*/

          LOG("continue-%d- send\"AT\"\r\n", iTimes);

        }

        else /*iTimes超过次数*/

        {

          iTimes = 0;

          LOG("AT error,%d times\r\n", EXE_AT_TIMES);         

          if(mdmPwrOnCnt < EXE_MDM_PWRON_TIMES)

          {

            MDM_STA = MDM_EXE_PWRON_ACT;      //进入开机流程

            LOG(".MDM_EXE_PWRON_ACT\r\n");

          }

          else

          {

            mdmPwrOnCnt = 0; /*开机次数清零*/

            MDM_STA = MDM_IDLE_STA;

            STOP_MDM_FSM(); /*MDM_FSM结束*/   

            gCnt.mdmTotalErr++;

            LOG("send \"AT\" %d times error,mdmTotalErr++\r\n", EXE_AT_TIMES);

          }

        }

      }     

      break;


    case MDM_WAIT_GSM_READY: /*等待GSM网络注册成功*/

      if(!mdmWaitGSMReady())

      {

        MDM_STA = MDM_START_INIT; /*GSM注册成功*/

        LOG("MDM_GSM_READY\r\n");

      }

      else if(gtimer.mdmFSMTimerout > WAIT_GSM_READY_MAX_TIME)

      {

        MDM_STA = MDM_START_INIT; /*GSM注册失败*/

        LOG("MDM_GSM_NO_READY\r\n");

      }

      break;



      /*MDM初始化配置*/ 

    case MDM_START_INIT: /*开始初始化*/

      LOG("\r\n*Step:%d,MDM_START_INIT\r\n", MDM_START_INIT);

      MDM_STA = MDM_TX_ATQINDI_CMD;

      break;

    #if 1    //190115   

    case MDM_TX_ATQINDI_CMD://AT+QINDI配置是否缓存接收到的数据 

      LOG("*%d<-:AT+QINDI=2[%d]\r\n", MDM_TX_ATQINDI_CMD, iTimes);

      mdm_send_cmd_noack((u8*)"AT+QINDI=2");  //0-不缓存 2-缓存模式     

      iTimes++;

      MDM_STA = MDM_WAIT_ATQINDI_RES;

      gtimer.mdmFSMTimerout = 0;

      break;

    case MDM_WAIT_ATQINDI_RES:

      if(!mdm_check_result((u8*)"OK"))

      {

        MDM_STA = MDM_TX_ATCMVERSION_CMD;

        LOG("->:OK[%d]\r\n", iTimes);       

        gCnt.fsmErrCnt = 0;

      }

      else if(!mdm_check_result((u8*)"ERROR"))

      {

        MDM_STA = MDM_TX_ATCMVERSION_CMD;

        LOG("->:ERROR[%d]\r\n", iTimes);       

        gCnt.fsmErrCnt = 0;

        if(iTimes < 3) //190220

        {

          MDM_STA = MDM_TX_ATQINDI_CMD;

        }

        else

        {

          iTimes = 0;

          MDM_STA = MDM_TX_ATCMVERSION_CMD;

          LOG("AT+QINDI=2,error 3 times!\r\n");       

          gCnt.fsmErrCnt++;         

        }

      }

      else if(gtimer.mdmFSMTimerout > 400)

      {

        if(iTimes < 3)

        {

          MDM_STA = MDM_TX_ATQINDI_CMD;

        }

        else

        {

          iTimes = 0;

          MDM_STA = MDM_TX_ATCMVERSION_CMD;

          LOG("AT+QINDI=2,error 3 times!\r\n");       

          gCnt.fsmErrCnt++;         

        }

      }

      break;

      #endif     



    /*查版本*/

    case MDM_TX_ATCMVERSION_CMD:

      LOG("*<-%d:AT+CMVERSION\r\n", MDM_TX_ATCMVERSION_CMD); 

      memset(USART1_RX_BUF, 0, sizeof(USART1_RX_BUF));   

      mdm_send_cmd_noack((u8*)"AT+CMVERSION");

      MDM_STA = MDM_WAIT_ATCMVERSION_RES;

      gtimer.mdmFSMTimerout = 0;

      break;

    case MDM_WAIT_ATCMVERSION_RES:     

      if(!mdm_check_str((u8*)"M6313"))

      { 

        char* p = strstr((const char*)USART1_RX_BUF, (const char*)"M6313"); /*USART1_RX_STA被mdm_check_str清0了*/

        if(NULL != p)//格式:M6313-MBRH0S02-release-EXT-20181025

        {

          char* p1 = NULL;                             

          p1 = strchr((const char*)USART1_RX_BUF, '-');    /*第一个'-'内容*/

          if(NULL !=p1)

          { 

            strncpy(mdmInfo.MDMSoftInfo, p1+1, 8); /*取"MBRH0S02"*/           

          }                 

          char* p2 = NULL;

          p2 = strrchr((const char*)USART1_RX_BUF, '-');  /*最后一个'-'内容*/

          if((NULL!=p2) && (p2!=p1))

          {

            strncpy(&mdmInfo.MDMSoftInfo[8], p2+3, 6);/*取"181025"*/

          }

          mdmInfo.MDMSoftInfo[14] = '\0';

          p1 = NULL; 

          p2 = NULL;                         

          LOG("Copy...\r\n");         

        }

        else

        {

          LOG("Copy error!\r\n");

        }         

        p = NULL;

        MDM_STA = MDM_TX_ATQITKA_CMD;       

        LOG("->:M6313...\r\n");       

      }

      else if(gtimer.mdmFSMTimerout > 200)

      {

        MDM_STA = MDM_TX_ATQITKA_CMD;     

        LOG("Fault\r\n");       

      }

      break; 


    /*TCP自动心跳 AT+QITKA=< keepalive >[,<keepidle>][,<keepinterval>][,< keepcount>]*/

    //MDM_AUTO_TICK_EN   

    case MDM_TX_ATQITKA_CMD:

      LOG("*<-%d:AT+QITKA=1,60,300,3\r\n", MDM_TX_ATQITKA_CMD);         

      mdm_send_cmd_noack((u8*)"AT+QITKA=1,60,300,3");

      MDM_STA = MDM_WAIT_ATQITKA_RES;

      gtimer.mdmFSMTimerout = 0;

      break;

    case MDM_WAIT_ATQITKA_RES:     

      if(!mdm_check_str((u8*)"OK"))

      {

        MDM_STA = MDM_TX_ATQSCLK_CMD;

        LOG("->:OK\r\n");     

      }

      else if(gtimer.mdmFSMTimerout > 200)

      {

        MDM_STA = MDM_TX_ATQSCLK_CMD;

        LOG("Fault\r\n");       

      }

      break;

    /*设置慢时钟*/

    case MDM_TX_ATQSCLK_CMD: /*慢时钟*/

      LOG("\r\n*Step:%d,AT+QSCLK\r\n", MDM_TX_ATQSCLK_CMD);

      mdm_send_cmd_noack((u8*)"AT+QSCLK=1"); /*开启慢时钟*///修改 lyn 2018.10.6

      MDM_STA = MDM_WAIT_ATQSCLK_RES;

      gtimer.mdmFSMTimerout = 0;

      break;

    case MDM_WAIT_ATQSCLK_RES:

      if(!mdm_check_str((u8*)"OK"))

      {

        MDM_STA = MDM_TX1_ATGSN_CMD;

        LOG("AT+QSCLK=1 ok\r\n");

      }

      else if(gtimer.mdmFSMTimerout > 200) /*1s超时*/

      {

        MDM_STA = MDM_TX1_ATGSN_CMD;

        LOG("AT+QSCLK=1 error\r\n");

      }

      break; 


    /*第1次读取IMEI*/

    case MDM_TX1_ATGSN_CMD:

      LOG("\r\n*Step:%d,read IMEI\r\n", MDM_TX1_ATGSN_CMD);

      mdm_send_cmd_noack((u8*)"AT+GSN"); /*读取IMEI*/

      MDM_STA = MDM_WAIT1_ATGSN_RES;

      gtimer.mdmFSMTimerout = 0;     

      break;

    case MDM_WAIT1_ATGSN_RES:/*读取IMEI*/

      if(!mdm_check_str((u8*)"OK")) /*查询到OK*/

      {

        Str2BCD(USART1_RX_BUF, (u8*)temp1IMEI);

        MDM_STA = MDM_TX2_ATGSN_CMD; /*第2次读取IMEI*/

        LOG("-1-get IMEI ok\r\n");

      }

      else if(gtimer.mdmFSMTimerout > 400) /*2s超时*/

      {

        MDM_STA = MDM_TX_ATCIMI_CMD;

        LOG("-1-get IMEI error\r\n");

      }     

      break; 


    /*第2次读取IMEI*/

    case MDM_TX2_ATGSN_CMD:

      LOG("\r\n*Step:%d,read IMEI\r\n", MDM_TX2_ATGSN_CMD);

      mdm_send_cmd_noack((u8*)"AT+GSN"); /*读取IMEI*/

      MDM_STA = MDM_WAIT2_ATGSN_RES;

      gtimer.mdmFSMTimerout = 0;     

      break;

    case MDM_WAIT2_ATGSN_RES:/*读取IMEI*/

      if(!mdm_check_str((u8*)"OK")) /*查询到OK*/

      {

        Str2BCD(USART1_RX_BUF, (u8*)temp2IMEI);

        MDM_STA = MDM_TX_ATCIMI_CMD;

        LOG("-2-get IMEI ok\r\n");

        if(memcmp(&temp1IMEI[0], &temp2IMEI[0], sizeof(temp2IMEI)) == 0) /*两次结果相等*/

        {

          LOG("read 2 times same IMEI\r\n");

          LOG("IMEI1:\r\n");

          printfHex(temp1IMEI,sizeof(temp1IMEI));

          LOG("IMEI2:\r\n");

          printfHex(temp2IMEI,sizeof(temp2IMEI));

          if(memcmp(&deviceInfo.deviceIMEI[0], &temp2IMEI[0], sizeof(temp2IMEI)) != 0)/*和旧IMEI比较*/

          {

            memcpy(&deviceInfo.deviceIMEI[0], &temp2IMEI[0], sizeof(temp2IMEI));

            writeFlash();              //保存参数

            LOG("updata IMEI ok\r\n");

          }

          else

          {

            LOG("old IMEI ok\r\n");

          }           

          memset(temp1IMEI, 0x00, sizeof(temp1IMEI));

          memset(temp2IMEI, 0x00, sizeof(temp2IMEI));                   

        }

        else

        {

          LOG("read 2 times different IMEI\r\n");

        } 

      }

      else if(gtimer.mdmFSMTimerout > 400) /*2s超时*/

      {

        MDM_STA = MDM_TX_ATCIMI_CMD;

        LOG("-2-get IMEI error\r\n");

      }     

      break;


    /*读取IMSI*/ 

    case MDM_TX_ATCIMI_CMD: /*读取IMSI*/

      LOG("\r\n*Step:%d,read IMSI\r\n", MDM_TX_ATCIMI_CMD);

      mdm_send_cmd_noack((u8*)"AT+CIMI");

      MDM_STA = MDM_WAIT_ATCIMI_RES;

      gtimer.mdmFSMTimerout = 0;       

      break;

    case MDM_WAIT_ATCIMI_RES:

      if(!mdm_check_str((u8*)"OK")) /*查询到OK*/

      {

        char tmpIMSI[8];

        Str2BCD(USART1_RX_BUF, (u8*)tmpIMSI); /*TBoxInfoType.deviceInfo.deviceIMSI*/

        MDM_STA = MDM_GPRS_INTI;

        LOG("get IMSI:\r\n");

        printfHex(tmpIMSI,sizeof(tmpIMSI));

        if(memcmp(&TBoxInfoType.deviceInfo.deviceIMSI[0], &tmpIMSI[0], sizeof(tmpIMSI)) != 0)/*和旧数据比较*/

        {

          memcpy(&TBoxInfoType.deviceInfo.deviceIMSI[0], &tmpIMSI[0], sizeof(tmpIMSI));

          writeFlash(); //保存参数

          LOG("updata IMSI ok\r\n");

        }

        else

        {

          LOG("old IMSI ok\r\n");

        }

        memset(tmpIMSI, 0x00, sizeof(tmpIMSI));

      }

      else if(gtimer.mdmFSMTimerout > 400) /*2s超时*/

      {

        MDM_STA = MDM_GPRS_INTI;

        LOG("get IMSI error\r\n");

      }     

      break;         



    /*GPRS配置*/

    case MDM_GPRS_INTI:

      LOG("\r\n*Step:%d,MDM_GPRS_INTI\r\n", MDM_GPRS_INTI);

      MDM_STA = MDM_TX_ATE_CMD;

      break;


    case MDM_TX_ATE_CMD:/*开关回显*/

      LOG("\r\n*Step:%d,%s\r\n", MDM_TX_ATE_CMD, ATEx);

      mdm_send_cmd_noack((u8*)ATEx); /*开关回显*/

      MDM_STA = MDM_WAIT_ATE_RES;

      gtimer.mdmFSMTimerout = 0;     

      break;

    case MDM_WAIT_ATE_RES:

      if(!mdm_check_str((u8*)"OK"))

      {

        MDM_STA = MDM_TX_ATCPIN_CMD;

        LOG("%s ok\r\n", ATEx);

      }

      else if(gtimer.mdmFSMTimerout > 200) /*1s超时*/

      {

        MDM_STA = MDM_TX_ATCPIN_CMD;

        LOG("ATEx error\r\n");

      }     

      break;             


    case MDM_TX_ATCPIN_CMD: /*非阻塞式,最大等待时长5s*/

      LOG("\r\n*Step:%d,AT+CPIN?\r\n", MDM_TX_ATCPIN_CMD);

      mdm_send_cmd_noack((u8*)"AT+CPIN?");

      MDM_STA = MDM_WAIT_ATCPIN_RES;

      gtimer.mdmFSMTimerout = 0;     

      break;

    case MDM_WAIT_ATCPIN_RES:

      if(!mdm_check_str((u8*)"READY")) /*查询*/

      {

        MDM_STA = MDM_TX_ATCCID_CMD;

        LOG("AT+CPIN? ok\r\n");

      }

      else if(gtimer.mdmFSMTimerout > WAIT_ATCPIN_MAX_TIME) /*超时,最大5s*/

      {

        MDM_STA = MDM_TX_ATCCID_CMD; /*next*/

        gCnt.mdmTotalErr++;

        SIM_Handler();/*SIM卡故障*/

        LOG("AT+CPIN? error\r\n");

      }     

      break;   


    case MDM_TX_ATCCID_CMD: /*查询SIM卡CCID*/

      LOG("\r\n*Step:%d,read CCID\r\n", MDM_TX_ATCCID_CMD);

      mdm_send_cmd_noack((u8*)"AT+CCID");

      MDM_STA = MDM_WAIT_ATCCID_RES;

      gtimer.mdmFSMTimerout = 0;           

      break;


    case MDM_WAIT_ATCCID_RES:

    if(!mdm_check_str((u8*)"+CCID:")) /*查询*/

    {

      char* tempCCID = NULL;

      u8 ccidSize = 21;


      tempCCID = (char*)malloc(sizeof(char)*ccidSize);       

      memset(tempCCID, 0x00, ccidSize);

      memcpy(tempCCID, &USART1_RX_BUF[10], ccidSize);//保存CCID

      tempCCID[20] = '\0'; /*添加结束符*/       

      LOG("tmpCCID:%s\r\n", tempCCID); 

      if(strstr((const char*)tempCCID, (const char*)"OK")== NULL) //无OK

      {

        if(strstr((const char*)tempCCID, (const char*)"\r\n")== NULL) //无回车换行       

        {

          memcpy(m6313Debug.ccid, tempCCID, ccidSize);//更新CCID

          m6313Debug.ccid[20] = '\0'; /*添加结束符*/

          LOG("newCCID:%s\r\n", m6313Debug.ccid); 

        }

        else

        {

          LOG("error\"OK\",");

          LOG("old CCID:%s\r\n", m6313Debug.ccid);         

        }

      }

      else

      {

        LOG("error\"0x0A,0x0D\"\r\n");

        LOG("old CCID:%s\r\n", m6313Debug.ccid);         

      }       

      free(tempCCID);


      MDM_STA = MDM_TX_ATCREG_CMD;                 

    }

    else if(gtimer.mdmFSMTimerout > WAIT_ATCCID_MAX_TIME) /*超时,5s*/

    {

      MDM_STA = MDM_TX_ATCREG_CMD;

      LOG("CCID get timeout! ");

      LOG("old CCID:%s\r\n", m6313Debug.ccid);

    }       

    break;

    case MDM_TX_ATCREG_CMD: /*查询2G网络是否注册*/

      LOG("\r\n*Step:%d,AT+CREG?\r\n", MDM_TX_ATCREG_CMD);

      mdm_send_cmd_noack((u8*)"AT+CREG?");

      MDM_STA = MDM_WAIT_ATCREG_RES;

      gtimer.mdmFSMTimerout = 0;     

      break;

    case MDM_WAIT_ATCREG_RES:

      if(!mdm_check_str((u8*)",1")) /*查询,已注册*/

      {   

        MDM_STA = MDM_TX_ATCSQ_CMD;

        LOG("AT+CREG? ok:1\r\n");

      }

      else if(!mdm_check_str((u8*)",5")) /*查询,漫游*/

      {   

        MDM_STA = MDM_TX_ATCSQ_CMD;

        LOG("AT+CREG? ok:5\r\n");

      }

      else if(gtimer.mdmFSMTimerout > WAIT_ATCREG_MAX_TIME) /*超时,3s*/

      {

        USART1_RX_STA=0;

        MDM_STA = MDM_TX_ATCSQ_CMD; /*进入下一步*/

        LOG("AT+CREG? error\r\n");

      }     

      break;     


    case MDM_TX_ATCSQ_CMD: /*查询当前信号质量*/

      LOG("\r\n*Step:%d,AT+CSQ\r\n", MDM_TX_ATCSQ_CMD);

      mdm_send_cmd_noack((u8*)"AT+CSQ");

      MDM_STA = MDM_WAIT_ATCSQ_RES;

      gtimer.mdmFSMTimerout = 0;       

      break;

    case MDM_WAIT_ATCSQ_RES:

      if(!mdm_check_str((u8*)"OK")) /*查询*/

      {

        u8 len;

        mdmInfo.signalIntensity = NMEA_Str2num(&USART1_RX_BUF[8],&len); /*得到MDM的CSQ*/               

        MDM_STA = MDM_TX_ATQICLOSE_CMD;

        LOG("MDM_CSQ=%d\r\n", mdmInfo.signalIntensity);

      }

      else if(gtimer.mdmFSMTimerout > 200) /*1s超时*/

      {

        MDM_STA = MDM_TX_ATQICLOSE_CMD;

        LOG("get CSQ error.\r\n");

      } 

      break;   


    /*AT+QICLOSE关闭TCPUDP连接*/         

    case MDM_TX_ATQICLOSE_CMD: /*关闭PDP使用场景*/

      LOG("\r\n*Step:%d,AT+QICLOSE\r\n", MDM_TX_ATQICLOSE_CMD);

      mdm_send_cmd_noack((u8*)"AT+QICLOSE");

      MDM_STA = MDM_WAIT_ATQICLOSE_RES;

      gtimer.mdmFSMTimerout = 0;     

      break;

    case MDM_WAIT_ATQICLOSE_RES:

      if(!mdm_check_str((u8*)"ERROR")) /*关闭连接失败*/

      {               

        MDM_STA = MDM_TX_ATQIDEACT_CMD; /*NEXT关闭PDP*/

        LOG("AT+QICLOSE ok:\"ERROR\"\r\n");

      }

      else if(!mdm_check_str((u8*)"CLOSE OK")) /*关闭连接成功*/

      {             

        MDM_STA = MDM_TX_ATQIDEACT_CMD; /*NEXT关闭PDP*/

        LOG("AT+QICLOSE ok:\"CLOSE OK\"\r\n");

      }

      else if(gtimer.mdmFSMTimerout > WAIT_ATQICLOSE_MAX_TIME) /*超时,最大2s*/

      {

        MDM_STA = MDM_TX_ATQIDEACT_CMD;  /*NEXT关闭PDP*/

        LOG("AT+QICLOSE error\r\n");

      }     

      break;


    /*AT+QIDEACT关闭PDP使用场景*/

    case MDM_TX_ATQIDEACT_CMD:

      LOG("\r\n*Step:%d,AT+QIDEACT\r\n", MDM_TX_ATQIDEACT_CMD);

      mdm_send_cmd_noack((u8*)"AT+QIDEACT");

      MDM_STA = MDM_WAIT_ATQIDEACT_RES;

      gtimer.mdmFSMTimerout = 0;     

      break;

    case MDM_WAIT_ATQIDEACT_RES:

      if(!mdm_check_str((u8*)"ERROR")) /*查询*/

      {               

        MDM_STA = MDM_TX_ATQIREGAPP_CMD;

        LOG("AT+QIDEACT ok:\"ERROR\"\r\n");

      }

      else if(!mdm_check_str((u8*)"DEACT OK")) /*查询*/

      {             

        MDM_STA = MDM_TX_ATQIREGAPP_CMD;

        LOG("AT+QIDEACT ok:\"DEACT OK\"\r\n");

      }

      else if(gtimer.mdmFSMTimerout > WAIT_ATQIDEACT_MAX_TIME) /*超时,最大45s*/

      {

        MDM_STA = MDM_TX_ATQIREGAPP_CMD;

        LOG("AT+QIDEACT error\r\n");

      }     

      break; 



    case MDM_TX_ATQIREGAPP_CMD: /*设置GPRS的APN(配置为 SIM卡签约对应的APN)*/

      LOG("\r\n*Step:%d,AT+QIREGAPP\r\n", MDM_TX_ATQIREGAPP_CMD);

      mdm_send_cmd_noack((u8*)"AT+QIREGAPP=\"CMNET\"");

      MDM_STA = MDM_WAIT_ATQIREGAPP_RES;

      gtimer.mdmFSMTimerout = 0;     

      break;     

    case MDM_WAIT_ATQIREGAPP_RES:

      if(!mdm_check_str((u8*)"OK")) /*查询*/

      {             

        MDM_STA = MDM_START_ATQIACT_CMD;

        LOG("AT+QIREGAPP ok\r\n");

      }

      else if(gtimer.mdmFSMTimerout > WAIT_ATQIREGAPP_MAX_TIME) /*超时,3s*/

      {

        MDM_STA = MDM_START_ATQIACT_CMD; /*NEXT*/

        LOG("AT+QIREGAPP error\r\n");

      }     

      break;

    case MDM_START_ATQIACT_CMD: /*开始激活PDP*/

      LOG("\r\n*Step:%d,MDM_START_ATQIACT_CMD\r\n", MDM_START_ATQIACT_CMD);

      iTimes = 0;

      MDM_STA = MDM_TX_ATQIACT_CMD;

      break; 

    case MDM_TX_ATQIACT_CMD: /*激活PDP,GPRS网络*/

      LOG("\r\n*step:%d,AT+QIACT\r\n", MDM_TX_ATQIACT_CMD);

      mdm_send_cmd_noack((u8*)"AT+QIACT");

      iTimes++;

      LOG("AT+QIACT,count-%d-!\r\n", iTimes);

      gtimer.mdmFSMTimerout = 0;

      MDM_STA = MDM_WAIT_ATQIACT_RES;     

      break; 

    case MDM_WAIT_ATQIACT_RES:

      if(!mdm_check_str((u8*)"OK")) /*查询到OK*/

      {       

        MDM_STA = MDM_START_TCP_SETUP; 

        LOG("AT+QIACT-OK[%d]\r\n", iTimes);       

      }

      else if(gtimer.mdmFSMTimerout > WAIT_ATQIACT_MAX_TIME) /*10秒超时*/

      {

        if(iTimes < EXE_ATQIACT_TIMES)

        {

          MDM_STA = MDM_TX_ATQIACT_CMD; /*继续激活PDP*/

          LOG(".AT+QIACT,Continue-%d-!\r\n", iTimes);

        }

        else /*iTimes超过次数*/

        {

          iTimes = 0;         

          MDM_STA = MDM_START_TCP_SETUP; /*NEXT*/ 

          LOG("AT+QIACT,%d times PDP active error\r\n", EXE_ATQIACT_TIMES);         

        }

      }     

      break; 


    /*建立TCP连接*/ 

    case MDM_START_TCP_SETUP:

      LOG("\r\n*Step:%d,MDM_START_TCP_SETUP\r\n", MDM_START_TCP_SETUP);

      MDM_STA = MDM_TX_ATQIMUX_CMD;

      break;   


    case MDM_TX_ATQIMUX_CMD: /*配置单路连接*/

      LOG("\r\n*Step:%d,AT+QIMUX\r\n", MDM_TX_ATQIMUX_CMD);

      mdm_send_cmd_noack((u8*)"AT+QIMUX=0");

      MDM_STA = MDM_WAIT_ATQIMUX_RES;

      gtimer.mdmFSMTimerout = 0;       

      break;

    case MDM_WAIT_ATQIMUX_RES:

      if(!mdm_check_str((u8*)"OK")) /*查询*/

      {             

        MDM_STA = MDM_TX_ATQIMODE_CMD;

        LOG("AT+QIMUX ok\r\n");

      }

      else if(gtimer.mdmFSMTimerout > 200) /*超时,1s*/

      {

        MDM_STA = MDM_TX_ATQIMODE_CMD; /*NEXT*/

        LOG("AT+QIMUX error\r\n");

      }       

      break;   


    case MDM_TX_ATQIMODE_CMD: /*配置非透传模式*/

      LOG("\r\n*Step:%d,AT+QIMODE\r\n", MDM_TX_ATQIMODE_CMD);

      mdm_send_cmd_noack((u8*)"AT+QIMODE=0"); /*非透传*/

      MDM_STA = MDM_WAIT_ATQIMODE_RES;

      gtimer.mdmFSMTimerout = 0;       

      break;

    case MDM_WAIT_ATQIMODE_RES:

      if(!mdm_check_str((u8*)"OK")) /*查询*/

      {             

        MDM_STA = MDM_TX_ATQIDNSIP_CMD;

        LOG("AT+QIMODE ok\r\n");

      }

      else if(gtimer.mdmFSMTimerout > 200) /*超时,1s*/

      {

        MDM_STA = MDM_TX_ATQIDNSIP_CMD; /*NEXT*/   

        LOG("AT+QIMODE error\r\n");

      }       

      break; 


    case MDM_TX_ATQIDNSIP_CMD: /*使用域名访问*/

      LOG("\r\n*Step:%d,AT+QIDNSIP\r\n", MDM_TX_ATQIDNSIP_CMD);

      mdm_send_cmd_noack((u8*)"AT+QIDNSIP=1"); /*非透传*/

      MDM_STA = MDM_WAIT_ATQIDNSIP_RES;

      gtimer.mdmFSMTimerout = 0;     

      break;

    case MDM_WAIT_ATQIDNSIP_RES:     

      if(!mdm_check_str((u8*)"OK")) /*查询*/

      {             

        MDM_STA = MDM_START_ATQIOPEN_CMD; /*NEXT*/

        LOG("AT+QIDNSIP ok\r\n");

      }

      else if(gtimer.mdmFSMTimerout > 400) /*超时2s*/

      {

        MDM_STA = MDM_START_ATQIOPEN_CMD; /*NEXT*/     

        LOG("AT+QIDNSIP error\r\n");

      } 

      break;   


    case MDM_START_ATQIOPEN_CMD: /*开始TCP连接*/

      LOG("\r\n*Step:%d,MDM_START_ATQIOPEN_CMD\r\n", MDM_START_ATQIOPEN_CMD);

      iTimes = 0;

      MDM_STA = MDM_TX_ATQIOPEN_CMD;

      break;

    case MDM_TX_ATQIOPEN_CMD:

      LOG("\r\n*Step:%d,AT+QIOPEN\r\n", MDM_TX_ATQIOPEN_CMD);


      if(devParam.secondTcp.addr[0] !=0)/*联网IP选择*/

      {

        TCP_Conncect(devParam.secondTcp.addr,devParam.secondTcp.port);

      }

      else{

        TCP_Conncect(IPaddr,IPport);}

      iTimes++;

      LOG("send\"AT+QIOPEN\",count-%d-\r\n", iTimes);   

      MDM_STA = MDM_WAIT_ATQIOPEN_RES;

      gtimer.mdmFSMTimerout = 0;     

      break;


    case MDM_WAIT_ATQIOPEN_RES:

      if(!mdm_check_str((u8*)"CONNECT OK")) /*查询CONNECT*/

      {             

        MDM_STA = MDM_WAIT_TCPSEND_CMD; /*TCP建立成功,进入空闲状态*/

        LOG(".get\"CONNECT OK\"\r\n");       

      }

      else if(!mdm_check_str((u8*)"ALREAY CONNECT"))

      {

        MDM_STA = MDM_WAIT_TCPSEND_CMD; /*TCP建立成功,进入空闲状态*/

        LOG(".get\"ALREAY CONNECT\"\r\n");       

      }

      else if(gtimer.mdmFSMTimerout > WAIT_ATQIOPEN_MAX_TIME) /*超时,30s*/

      {   

        LOG("count-%d-,MDM_FSM timeout!\r\n", iTimes);       

        if(iTimes < EXE_ATQIOPEN_TIMES)

        {

          MDM_STA = MDM_TX_ATQIOPEN_CMD; /*继续建立TCP*/

          LOG(".continue AT+QIOPEN!\r\n");

        }

        else /*iTimes超过次数*/

        {

          iTimes = 0;                   

          MDM_STA = MDM_IDLE_STA; /*中断*/       

          STOP_MDM_FSM(); /*MDM_FSM结束*/   

          cntMdm = 0; /*MDM连网失败*/

          gCnt.mdmTotalErr++; //MDM错误统计

          LOG("AT+QIOPEN:%d times exe error,TCP connect fail!\r\n",EXE_ATQIOPEN_TIMES);         

        }       

      }     

      break;

      /*进行延时发送任务*/

    case MDM_WAIT_TCPSEND_CMD:

      MDM_STA = MDM_WAIT_TCPSEND_RES; /*TCP建立成功,进入等待发送任务*/

      LOG("MDM_FSM:TCP connect suc!\r\n");

      gtimer.mdmFSMTimerout = 0;     

      break;     

    case MDM_WAIT_TCPSEND_RES:

      if(gtimer.mdmFSMTimerout > 400)  /*等待两秒*/

      {       

        MDM_STA = MDM_IDLE_STA; /*TCP建立成功,进入空闲状态*/

        MDM_NET_CONNECT_OK_HANDLE();

        STOP_MDM_FSM(); /*MDM_FSM结束*/   

      }       

      break; 

    default:

      break;

  }

}

 这就是我分享的2G网络模块联网的过程哈,里面代码是实践过的,如果大家有什么更好的思路,欢迎分享交流哈。

更多分享,扫码关注我

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 175,490评论 5 419
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 74,060评论 2 335
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 124,407评论 0 291
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 47,741评论 0 248
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 56,543评论 3 329
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 43,040评论 1 246
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 34,107评论 3 358
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 32,646评论 0 229
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 36,694评论 1 271
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 32,398评论 2 279
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 33,987评论 1 288
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 30,097评论 3 285
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 35,298评论 3 282
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 27,278评论 0 14
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 28,413评论 1 232
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 38,397评论 2 309
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 38,099评论 2 314