编写时间: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模组应答}wifiCmdType;
 
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模组没有应答
 } 
/*
 *********************************************************************************************************
 *    函 数 名: 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模组已有应答
      }          return FALSE;        //返回FALSE说明wifi模组没有应答
  }
  /*
 *********************************************************************************************************
 *    函 数 名: 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一键配网app esp8266一键配网并保存_重启

esp8266波特率设置

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

esp8266一键配网app esp8266一键配网并保存_IP_02

 

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

esp8266一键配网app esp8266一键配网并保存_重启_03

 

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

esp8266一键配网app esp8266一键配网并保存_UDP_04

 

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

esp8266一键配网app esp8266一键配网并保存_esp8266一键配网app_05

 

 

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

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

esp8266一键配网app esp8266一键配网并保存_IP_06

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

esp8266一键配网app esp8266一键配网并保存_esp8266一键配网app_05