esp8266 wifi模组手机一键配网,配置一次,下次重启设备后不需再进行配网

编写时间:2018年9月2日数组

#define  ATCMDLEN   20服务器

extern uint8_t usart3RecvEndFlag;
extern UART_HandleTypeDef huart3;
extern uint16_t dmaUsart3RxLen;
extern uint8_t dmaUsart3RxBuf[DATA_BUFFER_SIZE];
uint8_t wifi_config = 0;网络

typedef enum dataType
{
     WIFI_AT,              //检测wifi模组是否在线
     WIFI_CWMODE_DEF,      //配置WIFI模组为Station模式并保存到flash
     WIFI_RST,             //重启WIFI模块
     WIFI_CWAUTOCONN,      //使能上电自动链接AP(路由)
     WIFI_CWSTARTSMART,    //CWSTARTSMART
     WIFI_CWSTOPSMART,     //释放内存
     WIFI_CIPSTATUS_TWO,   //查询网络链接状态,STATUS:2,得到 IP
     WIFI_CIPSTATUS_THREE, //查询网络链接状态,已链接
     WIFI_CIPSTATUS_FOUR,  //查询网络链接状态,断开链接
     WIFI_CIPSTATUS_FIVE,  //查询网络链接状态,未链接到 WiFi
     WIFI_CWJAP_DEF,       //查看wifi信号强度
     WIFI_CIPMUX,          //开启多链接
     WIFI_CIPSTART_ZERO,   //建立0号路由器AP
     WIFI_CIPSTART_ONE,    //链接1号路由器AP
     WIFI_CIPSTART_TWO,    //链接2号路由器AP
     WIFI_CIPSTART_THREE,  //链接3号路由器AP
     WIFI_CIPCLOSE_ZERO,   //关闭esp8266模组与0号服务器的链接
     WIFI_CIPCLOSE_ONE,    //关闭esp8266模组与1号服务器的链接
     WIFI_CIPCLOSE_TWO,    //关闭esp8266模组与2号服务器的链接
     WIFI_CIPCLOSE_THREE   //关闭esp8266模组与3号服务器的链接
    
}dataCmd; //此处的dataCmd为枚举型enum dataType的别名函数


typedef  struct WIFICONFIGCMD
{
     uint8_t* wifiCmd;    //wifi模组AT指令
     uint8_t cmdLen;      //wifi模组AT指令数据长度
     uint8_t* wifiAsk;    //wifi模组应答ui

}wifiCmdType;3d

 

wifiCmdType  wificmd[ATCMDLEN]={
{(uint8_t*)"AT\r\n",DATALEN("AT\r\n")-1,(uint8_t*)"OK"},                                                                  //0
{(uint8_t*)"AT+CWMODE_DEF=1\r\n",DATALEN("AT+CWMODE_DEF=1\r\n")-1,(uint8_t*)"OK"},  //1
{(uint8_t*)"AT+RST\r\n",DATALEN("AT+RST\r\n")-1,(uint8_t*)"OK"},                                                //2
{(uint8_t*)"AT+CWAUTOCONN=1\r\n",DATALEN("AT+CWAUTOCONN=1\r\n")-1,(uint8_t*)"OK"}, //3
{(uint8_t*)"AT+CWSTARTSMART\r\n",DATALEN("AT+CWSTARTSMART\r\n")-1,(uint8_t*)"OK"},  //4
{(uint8_t*)"AT+CWSTOPSMART\r\n",DATALEN("AT+CWSTOPSMART\r\n")-1,(uint8_t*)"OK"},      //5
{(uint8_t*)"AT+CIPSTATUS\r\n",DATALEN("AT+CIPSTATUS\r\n")-1,(uint8_t*)"STATUS:2"},  //6
{(uint8_t*)"AT+CIPSTATUS\r\n",DATALEN("AT+CIPSTATUS\r\n")-1,(uint8_t*)"STATUS:3"},  //7
{(uint8_t*)"AT+CIPSTATUS\r\n",DATALEN("AT+CIPSTATUS\r\n")-1,(uint8_t*)"STATUS:4"},  //8
{(uint8_t*)"AT+CIPSTATUS\r\n",DATALEN("AT+CIPSTATUS\r\n")-1,(uint8_t*)"STATUS:5"},  //9
{(uint8_t*)"AT+CWJAP_DEF?\r\n",DATALEN("AT+CWJAP_DEF?\r\n")-1,(uint8_t*)"OK"},   //10
{(uint8_t*)"AT+CIPMUX=1\r\n",DATALEN("AT+CIPMUX=1\r\n")-1,(uint8_t*)"OK"},               //11
   {(uint8_t*)"AT+CIPSTART=0,\"UDP\",\"192.168.1.117\",8000\r\n",DATALEN("AT+CIPSTART=0,\"UDP\",\"192.168.1.117\",8000\r\n")-1,(uint8_t*)"0,CONNECT"},//12
   {(uint8_t*)"AT+CIPSTART=1,\"UDP\",\"192.168.1.117\",8888\r\n",DATALEN("AT+CIPSTART=1,\"UDP\",\"192.168.1.117\",8888\r\n")-1,(uint8_t*)"1,CONNECT"},//13
   {(uint8_t*)"AT+CIPSTART=2,\"UDP\",\"192.168.1.117\",9000\r\n",DATALEN("AT+CIPSTART=2,\"UDP\",\"192.168.1.117\",9000\r\n")-1,(uint8_t*)"2,CONNECT"},//14
   {(uint8_t*)"AT+CIPSTART=3,\"UDP\",\"192.168.1.117\",9999\r\n",DATALEN("AT+CIPSTART=3,\"UDP\",\"192.168.1.117\",9999\r\n")-1,(uint8_t*)"3,CONNECT"},//15
{(uint8_t*)"AT+CIPCLOSE=0\r\n",DATALEN("AT+CIPCLOSE=0\r\n")-1,(uint8_t*)"OK"},//16
{(uint8_t*)"AT+CIPCLOSE=1\r\n",DATALEN("AT+CIPCLOSE=1\r\n")-1,(uint8_t*)"OK"},//17
{(uint8_t*)"AT+CIPCLOSE=2\r\n",DATALEN("AT+CIPCLOSE=2\r\n")-1,(uint8_t*)"OK"},//18
{(uint8_t*)"AT+CIPCLOSE=3\r\n",DATALEN("AT+CIPCLOSE=3\r\n")-1,(uint8_t*)"OK"} //19
};调试

 

/*
*********************************************************************************************************
*    函 数 名: wifi_ack_check
*    功能说明: wifi模组应答检测函数
*    形    参: ack
*    返 回 值: TRUE\FALSE
*********************************************************************************************************
*/
uint8_t wifiAtAckCmp(uint8_t* ack)
{  
        uint8_t usart3RxBuf[200];
        uint16_t len;
        len = dma_Usart3_Receiv(usart3RxBuf,DATALEN(usart3RxBuf));
        if(strstr((const char *)usart3RxBuf,(const char*)ack)){
                    rs485Send(usart3RxBuf,len);
                    memset(usart3RxBuf,0,DATALEN(usart3RxBuf));
                    return TRUE;    //返回TRUE说明wifi模组已有应答
            }  
   
        return FALSE;       //返回FALSE说明wifi模组没有应答
}server

 

/*
*********************************************************************************************************
*    函 数 名: sendWifiCmd
*    功能说明: wifi模组发送函数
*    形    参: cmd,ack,waittime
*    返 回 值: TRUE\FALSE
*********************************************************************************************************
*/
uint8_t sendWifiCmd(uint8_t *cmd,uint8_t len,uint8_t *ack,uint16_t waittime)   //单片机给wifi模组发送AT指令
{
     DMA_usart3_send(cmd,len);
     delay_ms(waittime);
     if(wifiAtAckCmp(ack)){
          return TRUE;      //返回TRUE说明wifi模组已有应答
     }blog

          return FALSE;        //返回FALSE说明wifi模组没有应答
 }
 ip

/*
*********************************************************************************************************
*    函 数 名: wifiCheakAsk
*    功能说明: 检测esp8266 wifi是否在线函数
*    形    参: 无
*    返 回 值: 无
*********************************************************************************************************
*/ 
void wifiCheakAsk(void)           
{
     uint8_t i = 3;  //检测3次esp8266是否在线应答
     delay_ms(200);
     do{

           //检测ESP8266模组是否在线
          if(sendWifiCmd(wificmd[WIFI_AT].wifiCmd,wificmd[WIFI_AT].cmdLen,wificmd[WIFI_AT].wifiAsk,80))
          {
               printf("检测ESP8266模组成功,,在进行启动配置,请稍等......\r\n\r\n");
               break;
           }else{
               if(i == 1){
                    printf("检测ESP8266模组失败!\r\n\r\n");
                }
               continue;
          }         
     }while(--i);

 

/*
*********************************************************************************************************
*    函 数 名: ipConnectConfig
*    功能说明: esp8266绑定IP地址函数
*    形    参: 无
*    返 回 值: 无
*********************************************************************************************************
*/ 
 void  ipConnectConfig(void)    //链接路由器绑定IP地址函数
{    
      uint8_t i = 3,j = 5;
      printf("ESP8266模组重启中,请稍等......\r\n");
      delay_ms(200);              //延时等待wifi模组启动成功
      
    do{

           //第一次重启不成功,进行第二次重启
           if(sendWifiCmd(wificmd[WIFI_RST].wifiCmd,wificmd[WIFI_RST].cmdLen,wificmd[WIFI_RST].wifiAsk,80))
           { 
                printf("ESP8266模组重启成功!\r\n\r\n");
                wifiCheakAsk();       //检测ESP8266模组是否在线
                break;
           }else{
                if(i == 1){
                         printf("ESP8266模组重启未成功,请再次重启设备!\r\n\r\n");
                    }
                continue;
             }
        
        }while(i--);            
        delay_xs(6);        //延时6秒,确保重启成功!
        
/*  2:得到 IP     3:已链接
    4:断开链接    5:未链接到 WiFi
        须要注意的是:wifi信号很差的时候,也检测不出网络状态,如网络很差时,检测到的STATUS状态为5,而不是2*/      
        do{
           if(sendWifiCmd(wificmd[WIFI_CIPSTATUS_TWO].wifiCmd,wificmd[WIFI_CIPSTATUS_TWO].cmdLen,wificmd[WIFI_CIPSTATUS_TWO].wifiAsk,80))//第一次发送确认是否链接已链接IP,若是没有确认(没有收到已链接到路由状态),多是wifi模组正忙于其它操做
           {
                    wifi_config = 1;                 //智能配置标志,1为已经配置过,下次设备重启不须要进行再进行配置
                    printf("ESP8266模组已得到路由器IP!\r\n\r\n");    
                    break;
             }else{
                   if(j == 1){                    //最后一次检测都连不上网络,则打印连不上网络的状况和网络所处的状态
                        delay_ms(200);
                        /*获取esp8266 wifi模组的链接状态*/
                      if(sendWifiCmd(wificmd[WIFI_CIPSTATUS_THREE].wifiCmd,wificmd[WIFI_CIPSTATUS_THREE].cmdLen,wificmd[WIFI_CIPSTATUS_THREE].wifiAsk,80)){
                        printf("ESP8266模组已与路由器链接!\r\n");
                        printf("重启ESP8266模组:\r\n");
                        if(sendWifiCmd(wificmd[WIFI_RST].wifiCmd,wificmd[WIFI_RST].cmdLen,wificmd[WIFI_RST].wifiAsk,50))
                         {
                               printf("ESP8266模组重启成功!\r\n\r\n");
                          }else{
                               printf("ESP8266模组重启未成功!\r\n\r\n");
                          }
                        delay_ms(500);    
 }else if(sendWifiCmd(wificmd[WIFI_CIPSTATUS_FOUR].wifiCmd,wificmd[WIFI_CIPSTATUS_FOUR].cmdLen,wificmd[WIFI_CIPSTATUS_FOUR].wifiAsk,60)){
                        printf("ESP8266模组已与路由器断开链接!\r\n");
                        printf("重启ESP8266模组:\r\n");
                                             if(sendWifiCmd(wificmd[WIFI_RST].wifiCmd,wificmd[WIFI_RST].cmdLen,wificmd[WIFI_RST].wifiAsk,50))
                                        {
                                                printf("ESP8266模组重启成功!\r\n\r\n");
                                        }else{
                                                printf("ESP8266模组重启未成功!\r\n\r\n");
                                        }
                                        delay_xs(4);    //延时4秒

                        }else{
                                        printf("WIFI信号很差,请检查WIFI信号强弱,或ESP8266模组第一次链接网络,须要进行配网!\r\n");
                                        printf("重启ESP8266模组:\r\n");
                                        if(sendWifiCmd(wificmd[WIFI_RST].wifiCmd,wificmd[WIFI_RST].cmdLen,wificmd[WIFI_RST].wifiAsk,50))
                                        {
                                                printf("ESP8266模组重启成功!\r\n\r\n");
                                        }else{
                                                printf("ESP8266模组重启未成功!\r\n\r\n");
                                        }
                                        delay_ms(500);    
                            }                  
                    }
          continue;                    
             }        
        }while(j--);            
 
        if(wifi_config == 0){  //wifi_config = 0,说明是第一次配网,下次重启wifi模组不须要进行配网
                printf("配置ESP8266模组为Station模式并保存到flash:\r\n");
                if(sendWifiCmd(wificmd[WIFI_CWMODE_DEF].wifiCmd,wificmd[WIFI_CWMODE_DEF].cmdLen,wificmd[WIFI_CWMODE_DEF].wifiAsk,80))
                {
                        printf("配置ESP8266模组为Station模式成功!\r\n\r\n");
                }else{
                        printf("配置ESP8266模组为Station模式未成功!\r\n\r\n");
                }
                delay_ms(200);
                printf("重启ESP8266模组:\r\n");
                if(sendWifiCmd(wificmd[WIFI_RST].wifiCmd,wificmd[WIFI_RST].cmdLen,wificmd[WIFI_RST].wifiAsk,80))//重启wifi模组,使设置生效
                {
                        printf("ESP8266模组重启成功!\r\n\r\n");
                }else{
                        printf("ESP8266模组重启未成功!\r\n\r\n");
                }
                                
                delay_ms(800);                
                if(sendWifiCmd(wificmd[WIFI_CWAUTOCONN].wifiCmd,wificmd[WIFI_CWAUTOCONN].cmdLen,wificmd[WIFI_CWAUTOCONN].wifiAsk,80))
                {
                        printf("使能ESP8266模组上电自动链接路由器!\r\n\r\n");
                }else{
                        printf("未成功使能ESP8266模组上电自动链接路由器!\r\n\r\n");
                }
                                
                delay_ms(500);    
                if(sendWifiCmd(wificmd[WIFI_CWSTARTSMART].wifiCmd,wificmd[WIFI_CWSTARTSMART].cmdLen,wificmd[WIFI_CWSTARTSMART].wifiAsk,80))
                {
                        printf("成功配置ESP8266模组智能配网命令!\r\n\r\n");
                }else{
                        printf("未能成功配置ESP8266模组智能配网命令!\r\n\r\n");
                }
                                
                printf("请打开您的手机进行网络配置链接......\r\n\r\n\r\n\r\n\r\n\r\n");
                do{                    
                    if(usart3RecvEndFlag == 1){
                            usart3RecvEndFlag = 0;
                            dmaUsart3RxLen = 0;
                            memset(dmaUsart3RxBuf,0,DATA_BUFFER_SIZE);
                            delay_xs(10);    //延时10秒
                                                             if(sendWifiCmd(wificmd[WIFI_CWSTOPSMART].wifiCmd,wificmd[WIFI_CWSTOPSMART].cmdLen,wificmd[WIFI_CWSTOPSMART].wifiAsk,80))
                            {
                                    printf("ESP8266模组释放内存!\r\n\r\n");    
                                    delay_xs(3);//延时3秒
                                    if(sendWifiCmd(wificmd[WIFI_CIPSTATUS_TWO].wifiCmd,wificmd[WIFI_CIPSTATUS_TWO].cmdLen,wificmd[WIFI_CIPSTATUS_TWO].wifiAsk,60)){
                                        printf("一键配网成功!\r\n\r\n");
                                        wifi_config = 1;//wifi_config = 1,说明第一次配网成功,下次重启wifi模组不须要进行配网
                                        break;
                                    }else{
                                        printf("一键配网失败!\r\n\r\n");
                                        break;
                                    }                                
                             }        
                         }
                    }while(1);                                                         
                    delay_ms(200);
                    printf("检测ESP8266模组的信号强度!\r\n");
                    DMA_usart3_send(wificmd[WIFI_CWJAP_DEF].wifiCmd,wificmd[WIFI_CWJAP_DEF].cmdLen);
                    delay_ms(200);
                    if(usart3RecvEndFlag == 1){
                            usart3RecvEndFlag = 0;
                            rs485Send(dmaUsart3RxBuf,dmaUsart3RxLen);
                            dmaUsart3RxLen = 0;
                            memset(dmaUsart3RxBuf,0,DATA_BUFFER_SIZE);
                     }             
            }
}        

/*
*********************************************************************************************************
*    函 数 名: serversConnectConfig
*    功能说明: esp8266 wifi链接服务器函数
*    形    参: 无
*    返 回 值: 无
*********************************************************************************************************
*/ 
void serversConnectConfig(void)    //绑定IP地址成功后,进行链接服务器
{            
          if(sendWifiCmd(wificmd[WIFI_CIPSTATUS_TWO].wifiCmd,wificmd[WIFI_CIPSTATUS_TWO].cmdLen,wificmd[WIFI_CIPSTATUS_TWO].wifiAsk,60))
            {   
                    printf("ESP8266模组已绑定IP地址,请进行往下配置!\r\n\r\n");
                    delay_ms(200);
                    printf("ESP8266模组开启多链接模式:\r\n");
                    if(sendWifiCmd(wificmd[WIFI_CIPMUX].wifiCmd,wificmd[WIFI_CIPMUX].cmdLen,wificmd[WIFI_CIPMUX].wifiAsk,80))
                    {
                            printf("ESP8266模组成功开启多链接模式!\r\n\r\n"); 
                    }else{
                            printf("ESP8266模组开启多链接模式失败!\r\n\r\n"); 
                    }
                                
                    delay_ms(200);
                    printf("链接IP地址为:192.168.1.117,端口号为8000的服务器:\r\n");
                    if(sendWifiCmd(wificmd[WIFI_CIPSTART_ZERO].wifiCmd,wificmd[WIFI_CIPSTART_ZERO].cmdLen,wificmd[WIFI_CIPSTART_ZERO].wifiAsk,80))
                    {
                            printf("成功链接IP地址为:192.168.1.117,端口号为8000的服务器!\r\n\r\n");
                    }else{
                            printf("链接IP地址为:192.168.1.117,端口号为8000的服务器失败!\r\n\r\n");
                    }
        }                
}     

 

/*
*********************************************************************************************************
*    函 数 名: esp8266SendData
*    功能说明: esp8266 wifi注册函数
*    形    参: databuf,len
*    返 回 值: 无
*********************************************************************************************************
*/ 
void esp8266SendData(uint8_t *databuf,uint8_t len)   //链接好服务器,开始往服务器发注册包进行注册
{  
      uint8_t str[50];
      sprintf((char *)str,"AT+CIPSEND=0,%d\r\n",len);    //把数组的数据长度数字改成字符串加到AT指令里面
    
        printf("数据发送预先配置:\r\n");
        if(sendWifiCmd(str,strlen((char*)str),(uint8_t*)"OK",80))
        {
            printf("数据发送预先配置成功!\r\n\r\n");
        }else{
            printf("数据发送预先配置失败!\r\n\r\n");
        }
                                    
        delay_ms(20);
    //if(sendWifiCmd((uint8_t*)"我是心跳包!\r\n",DATALEN("我是心跳包!\r\n")-1,(uint8_t*)"OK",80))
        if(sendWifiCmd(databuf,len,(uint8_t*)"OK",80))
        {
            printf("数据发送成功!\r\n\r\n");
         }else{
            printf("数据发送失败!\r\n\r\n");
         }                                            

//         if(sendWifiCmd((uint8_t*)"AT+CIPCLOSE=0\r\n",DATALEN("AT+CIPCLOSE=0\r\n")-1,(uint8_t*)"OK",80))
//         {
//                        printf("ESP8266模组解绑IP地址成功!\r\n\r\n"); 
//            }else{
//                        printf("ESP8266模组解绑IP地址失败!\r\n\r\n"); 
//            }
}
 

void wifiDataReceiv(void)
{
        printf("数据发送预先配置:\r\n");
        if(sendWifiCmd((uint8_t*)"AT+CIPSEND=0,24\r\n",DATALEN("AT+CIPSEND=0,24\r\n")-1,(uint8_t*)"OK",80))
        {
                printf("数据发送预先配置成功!\r\n\r\n");
        }else{
                printf("数据发送预先配置失败!\r\n\r\n");
        }
                                    
        delay_ms(20);
        
        if(sendWifiCmd((uint8_t*)"我是心跳包,请求注册!\r\n",DATALEN("我是心跳包,请求注册!\r\n")-1,(uint8_t*)"OK",80))
        {
                printf("心跳包发送成功!\r\n\r\n");
         }else{
                printf("心跳包发送失败!\r\n\r\n");
         }
     
      while(1){
          if(usart3RecvEndFlag == 1){
                    usart3RecvEndFlag = 0;
                    rs485Send(dmaUsart3RxBuf,dmaUsart3RxLen);                  
                    dmaUsart3RxLen = 0;
                    memset(dmaUsart3RxBuf,0,DATA_BUFFER_SIZE);            
            }    
        }         

}

 

实现功能

esp8266 wifi模组手机一键配网(接收到wifi模组的AT指令应答后,单片机进行作出判断,并在串口调试助手上把wifi的AT指令应答和单片机执行的动做打印出来),配网成功,单片机经过esp8266 wifi模组透传发数据到网络调试助手上的模拟服务器。配置一次,下次重启设备后不需再进行配网,除非设备换了地方,或者换了路由器才须要再进行手机配网。

第一次ESP8266进行手机配网

因为在调程序过程当中,让esp8266自动链接到了网络。如今只能链接到一个路由器(仍是蹭别人的,嘻嘻),为了能实现上面的功能,如今先让esp8266恢复出厂设置,而后进行手机配网。

esp8266恢复出厂设置

esp8266波特率设置

esp8266恢复出厂设置后波特率为默认的115200,此处的波特率为9600,故设置波特率为9600。

 

初始化成功后,等待手机智能配网

 

esp8266配置(链接路由器的路由器,esp8266和路由器是绑定不一样的IP地址,但在同一个网段)成功后,再链接到服务器。

 

链接到服务器后,往服务器发送数据,连续发送三次数据,服务器也接收到三次esp8266发来的数据。

 

 

第二次重启,不须要手机配网

esp8266重启后进行初始化,自动绑定IP地址,直接链接到服务器,而后往服务器发送数据。

服务器接收到esp8266透传上发的数据