基于WIFI模块(ESP8266)与非同一个局域网内服务器建立连接

前一篇文章讲述的是两个局域网间应该如何搭建连接的方法,这篇文章将讲述,这种方法的具体实施过程。


案例简述:

以WIFI模块(ESP8266)为开发对象,处在局域内网中的WIFI模块,连接到另外一个局域内网的TCP服务器,形成WIFI模块和服务器之间通信。本文先以电脑控制WIFI模块的连接,熟悉AT指令的使用,再通过编程手段,由单片机去控制WIFI模块,深入学习。


一.电脑端调试,控制WIFI模块的连接

说明:将WIFI模块通过串口与电脑连接,电脑通过串口调试软件给模块发送AT指令,控制WIFI模块与其他局域网内的服务器建立连接。


步骤:

1. 所需条件:

1)两台PC机,一个路由器,确保有台电脑可联网,并且路由器也联网,并分别连接在不同的局域网内,(支招:没有路由器的可以通过一台电脑开WIFI作为路由器,但确保是两个局域网内。没有两个局域网的,可以用手机开wifi热点给电脑提供网络,本实验不怎么费手机流量,勿担心)

2)联网的电脑(B电脑)安装花生壳软件(注意用的是穿透版),登入保持在线。

3)在有花生壳的电脑(B电脑)开启网络调试助手软件,另一台电脑(A电脑)开启串口调试软件。

4)有串口调试软件的电脑(A电脑),通过USB转TTL线与WIFI模块相连接。

前期准备工作如下图:
花生壳软件:
这里写图片描述

网络调试助手:
这里写图片描述
串口调试助手:
这里写图片描述

wifi模块与电脑串口连接(只需要TX,RX,VCC,GND引脚)
这里写图片描述


2. WIFI 模块连接到路由器

通过串口调试助手给wifi模块发送AT指令,控制模块。

1)复位WIFI模块,指令:AT+RST(注意发送指令后必须加换行,下面同理)

指令说明:
这里写图片描述

指令实现:
这里写图片描述

1)选择模式,指令:AT+CWMODE=3
指令说明:
这里写图片描述
指令实现:
这里写图片描述
1)连接到路由器,指令:AT+ CWJAP =”ldy”,”99999999”(路由器名称和密码,只能是非中文名称)
指令说明:
这里写图片描述
指令实现:
这里写图片描述


3. 模块与其他局域网服务器建立TCP连接

1)在B电脑上开启花生壳和网络调试助手,其中花生壳被映射的地址应为电脑本机IP地址,端口任意。网络调试助手上的IP和端口应该设置为被花生壳所映射的IP和端口。IP被花生壳映射到外网域名和端口号,是将要被WIFI模块连接的外网地址。如图:
这里写图片描述
2)启动单连接,指令:AT+ CIPMUX =0
指令说明:
这里写图片描述
指令实现:

这里写图片描述

3)连接到TCP服务器,

AT+CIPSTART=”TCP”,”14z95r6389.iask.in”,35447(改指令可以通过域名和端口号去连接,也可以通过IP和端口号连接,由于被穿透后是域名,故采用域名形式连接)
指令描述:
这里写图片描述
指令实现:
这里写图片描述

4)发送消息 AT+CIPSEND=5(5指的要发送消息的长度)
指令说明:
这里写图片描述
指令描述:
WIF模块端发送:
这里写图片描述

服务器端接收:
这里写图片描述

5)接收服务器(接收到消息会有“+IPD”的数据头)
说明:
这里写图片描述
接收实现:(接收到服务器端发的”zzz”字符)
这里写图片描述



二.单片机实现控制WIFI模块与服务器连接

从上面电脑端实现了,对WIFI模块连接到路由器后,再与服务器建立连接的过程,都是通过AT指令实现的,目的是为了熟悉AT指令的使用和调试。接下来就可以比较容易的通过单片机来控制WIFI模块,将需要发送的AT指令写入程序中。

实验内容:单片机控制WIFI模块,给服务器端发送长度为7位的字符串”abcdefg”


1.硬件条件

基于STM32单片机,通过USART3与WiFi模块相连接。


2.程序核心代码

本人已经写好了发送AT指令的封装函数,可灵活实现每个指令的定时等待和多次重发功能。可大大提高模块使用的稳定性,现在附上主要代码供参考。

主函数如下:

int main(void)
{   //通过域名形式连接到服务器
     char *string 
         ="AT+CIPSTART=\"TCP\",\"14z95r6389.iask.in\",35447"; 
    char *Seddstr = "abcdefg"; //被发送的字符串

    ALL_init();//初始化各种外设

    LED_ALL2_ON;
    delay_ms(1000);
    WIFI_AT_Command( "AT+RST","ready",5,2,ENABLE);
    delay_ms(1000);

    if(Send_wifiAT("AT+CWSAP?")==0)//判断是否连接上路由器
    {
        WIFI_AT_Command("AT+CWMODE=3","OK",3,2,DISABLE); //STATION兼AP模式
              WIFI_AT_Command("AT+CWJAP=\"ldy\",\"99999999\"","CONNECTED",10,3,DISABLE); //连接的到路由器,需要等待较长时间

    }   

    WIFI_AT_Command("AT+CIPMUX=0","OK",3,2,DISABLE);    //单连接

    WIFI_AT_Command((char*)string,"OK",5,3,ENABLE);
    //连接到服务器
    SendDATA_wifi(Seddstr,strlen(Seddstr));
   //发送数据
    while(1)
    {

    }
}

发送AT指令封装函数如下:(自写的封装函数,可供网友移植)

/*
函数:WIFI_AT_Command
功能:(智能化发送指令)在规定时间内,可多次重发某个指令,多次发送失败可复位
参数:b:发送内容,a:等待接收内容,timeout_S:发单次内最多允许等待          的时间,ReSendcount:最多可以重复发几次(失败情况),EN_Reset:如果失败是否复位机器。

返回: 成功回1  失败回0
*/

char WIFI_AT_Command(char *b,char *a,u8 timeout_S , char ReSendcount,FunctionalState EN_Reset)
{
    u16 count =0;
  u8 i = 0;

    WaitACKflag = 1;  //WaitACKflag用于防止重入函数  strstr

    CLR_Buf3();
    ACK_Command = a;

    for(i =1 ; (i<= ReSendcount && WaitACKflag); i++) //若失败 ,重复发送ReSendcount次
    {
        CLR_Buf3(); 
        USART_Puts(USART3 ,b);
        USART_Puts(USART3 ,"\r\n");


        while(WaitACKflag) //判断在中断里,等待变成0
        {
            count ++;
            delay_ms(5);    
            if(count >200*timeout_S) //最多允许等待timeout_S S
            {
                count=0;
                break;
            }

        }
    }

    ACK_Command="";
    WaitACKflag =0;

    if(count == 0 && i == ReSendcount) //重复发送ReSendcount次,还没接收到响应指令(都失败)
    {
        if(EN_Reset == ENABLE)//如果使能了复位模式
        {
            __set_FAULTMASK(1);      // 关闭所有中端
            NVIC_SystemReset();     //软件直接复位(重来)            

        }
        return 0;
    }

    return 1;
}

给服务器发送数据封装函数:

/**
函数:SendDATA_wifi
功能:给服务器发送数据
参数:a:发送的数据   length:发送的长度
返回: 
**/
void SendDATA_wifi(char *a ,u16 length)
{
    char Buf[30] = "";

    sprintf(Buf,"AT+CIPSEND=%d",length);

    WIFI_AT_Command(Buf,">",3,2,ENABLE);
    WIFI_AT_Command(a,"SEND OK",4,2,ENABLE);

}

串口USART3接收中断函数:

/**
 函数名  : USART3_IRQHandler
 描述    : 串口3中断服务程序
 输入    : 无
 返回    : 无 
说明    : 
**/
void USART3_IRQHandler(void)                    
{
    u8  ch=0;

    if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
    {       
            USART_ClearITPendingBit(USART3, USART_IT_RXNE);
            ch = USART_ReceiveData(USART3);


            Wifi_RXbuf[Wificount++] =(char)ch;

            if(ch == '\n' || Wificount>=Uart3bufMAX)//防止超限
            {
                Wificount =0;
            }


            if(WaitACKflag ==1) //将判断strstr函数写在中断里,WaitACKflag用于防止重入函数  
            {
                if(strstr(Wifi_RXbuf,ACK_Command)!=NULL)
                {
                    WaitACKflag=0;
                }

            }
            else
            {
                Judge_UART3_box();//对接收服务器接收消息的处理
            }


    }
}

接收服务器消息函数:

/**
函数:Judge_UART3_box
功能:接收服务器消息判断
参数:
返回:
**/
void Judge_UART3_box()
{
    if(strstr(Wifi_RXbuf,"+IPD")!=NULL)
    {
        //用户自行定义

    }
}

3.实验现象

服务器端可以接收到WIFI模块的数据如图:(服务器端也可以给WIFI模块发数据来控制单片机执行,接收函数也封装好在上面的代码中,感兴趣的可以做些相关实验)
这里写图片描述

猜你喜欢

转载自blog.csdn.net/ludaoyi88/article/details/62236644