基於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模塊發數據來控制單片機執行,接收函數也封裝好在上面的代碼中,感興趣的可以做些相關實驗)
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章