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

作者:良知犹存

转载授权以及围观:欢迎添加微信公众号: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网络模块联网的过程哈,里面代码是实践过的,如果大家有什么更好的思路,欢迎分享交流哈。


友情提醒: 请添加客服微信进行免费领取流量卡!
QQ交流群:226333560 站长微信:qgzmt2

原创文章,作者:sunyaqun,如若转载,请注明出处:https://www.dallk.cn/872.html

(0)
sunyaqunsunyaqun
上一篇 2023年9月21日
下一篇 2023年9月21日

相关推荐

发表回复

登录后才能评论