前言:
實現功能概要
STM32使用AT指令控制Wi-Fi以TCP方式連接咱上節安裝的Web服務器,然后使用http的get協議獲取雲端文本文件里面的內容,
然后把獲取的數據顯示在OLED液晶屏.
效果圖
實現功能的前提
1.在雲端的電腦上的Web服務器的根目錄放一個文件
注:以后Web服務器肯定還要做其它功能,所以最好在根目錄多建幾個文件夾,區分開各個功能,這個不用我說了吧!
我在根目錄(html)建了一個 hardware文件夾-->STM32_AT8266 文件夾,然后里面放了 updatainfo.txt 文件
2.文件內容 {"version":"1.02.56"} 一個JSON格式的數據,大家隨意都可以
測試一下文件是不是可以獲取
http://47.92.31.46/hardware/STM32_AT8266/updatainfo.txt 根據自己的哈,這是我的
單片機如何實現
網頁上是直接輸入 http://47.92.31.46/hardware/STM32_AT8266/updatainfo.txt
那樣輸入以后端口號默認是 80,所以不需要寫端口號
http://47.92.31.46/hardware:80/STM32_AT8266/updatainfo.txt 和上面的等價
實際上是先用TCP連接了IP地址: 47.92.31.46 端口號:80
然后發送:"GET /hardware/STM32_AT8266/updatainfo.txt HTTP/1.1\r\nHost: 47.92.31.46\r\n\r\n" HTTP的get協議
下圖是測試截圖
所以單片機只需要控制網絡模塊以TCP方式連接IP為: 47.92.31.46 端口號:80的服務器
然后發送 "GET /hardware/STM32_AT8266/updatainfo.txt HTTP/1.1\r\nHost: 47.92.31.46\r\n\r\n" 即可
程序下載測試
1,硬件設置: 短接STM32 PB2 和 WIFI RST (以后均采用硬件復位)
2,下載單片機程序
3,如果想讓WIFI連接路由器,可直接 去掉屏蔽
如果采用以上步驟,可略過 " WIFI配網,讓WIFI連接路由器 " 部分,編譯下載程序后,即可實現功能!
WIFI配網,讓WIFI連接路由器:
打開可以配網的APP,給Wi-Fi配網
請參考基礎篇: https://www.cnblogs.com/yangfengwu/p/11760590.html
最終效果
等待大約5S 如果一直不顯示可能是我動了服務器!!!
應用到自己的服務器
1.修改單片機程序訪問的Web服務器的IP地址和端口號 訪問文件的路徑自己隨意
2.按照單片機設置的訪問的路徑放置文件,
3.用自己的瀏覽器測試一下,如果測試可以獲取,把程序下載到單片機即可
程序說明(不走配網步驟)
1,代碼中連接的服務器信息,和獲取的文件路徑在這里設置的
2,去掉屏蔽,省去配網步驟
3.在 Init8266() 里面控制連接路由器
4,在AutoConnectTCP(); 里面,單片機通過AT指令配置8266以TCP透傳模式方式連接Web服務器
5.進入主循環
程序說明(走配網步驟)
1,按鈕按下3S執行配網
2,配網程序
3,配網成功,執行連接TCP服務器程序
注:此時主循環一直運行,使用的非阻塞框架!
注:本身主循環就是每隔5S發送一次 http get協議,有可能有人覺得上面就是多此一舉,因為
其實我只是給大家一個思路,有時候第一次連接上服務器確實需要發送了個數據,告訴服務器或者別的客戶端我上線了.
注意我的串口里面是處理了HTTP數據
1.這是返回的HTTP數據
HTTP/1.1 200 OK ----------可以獲取數據 Server: openresty/1.15.8.2 Date: Wed, 16 Oct 2019 14:14:03 GMT Content-Type: text/plain Content-Length: 21 ----------真實數據的個數 Last-Modified: Sat, 12 Oct 2019 18:36:33 GMT Connection: keep-alive ETag: "5da21d31-15" Accept-Ranges: bytes ----------這里有個\r\n ----------這里還有個\r\n {"version":"1.02.56"} ----------真實數據
2.我寫的解析函數
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { Res =USART_ReceiveData(USART1); //讀取接收到的數據 Usart1ReadBuff[Usart1ReadCnt] = Res; //接收的數據存入數組 Usart1ReadCnt++; if(Usart1ReadCnt > Usart1ReadLen -10)//防止數組溢出 { Usart1ReadCnt = 0; } Usart1IdleCnt = 0; //解析http數據-------------------------------Start //HTTP/1.1 200 OK if(!HttpHeadOK) { if(Res=='H' && HttpHeadCnt==0)HttpHeadCnt++; else if(Res=='T' && HttpHeadCnt==1)HttpHeadCnt++; else if(Res=='T' && HttpHeadCnt==2)HttpHeadCnt++; else if(Res=='P' && HttpHeadCnt==3)HttpHeadCnt++; else if(Res=='/' && HttpHeadCnt==4)HttpHeadCnt++; else if(Res=='1' && HttpHeadCnt==5)HttpHeadCnt++; else if(Res=='.' && HttpHeadCnt==6)HttpHeadCnt++; else if(Res=='1' && HttpHeadCnt==7)HttpHeadCnt++; else if(Res==' ' && HttpHeadCnt==8)HttpHeadCnt++; else if(Res=='2' && HttpHeadCnt==9)HttpHeadCnt++; else if(Res=='0' && HttpHeadCnt==10)HttpHeadCnt++; else if(Res=='0' && HttpHeadCnt==11)HttpHeadCnt++; else if(Res==' ' && HttpHeadCnt==12)HttpHeadCnt++; else if(Res=='O' && HttpHeadCnt==13)HttpHeadCnt++; else if(Res=='K' && HttpHeadCnt==14){HttpHeadOK = 1;HttpHeadCnt=0;HttpDataLength=0;} else { HttpHeadCnt=0; } } //Content-Length: XXXXXXXX if(HttpHeadOK && !HttpDataLengthOK)//獲取http發過來的數據個數 { if(Res=='-' && HttpHeadCnt==0) HttpHeadCnt++; else if(Res=='L' && HttpHeadCnt==1)HttpHeadCnt++; else if(Res=='e' && HttpHeadCnt==2)HttpHeadCnt++; else if(Res=='n' && HttpHeadCnt==3)HttpHeadCnt++; else if(Res=='g' && HttpHeadCnt==4)HttpHeadCnt++; else if(Res=='t' && HttpHeadCnt==5)HttpHeadCnt++; else if(Res=='h' && HttpHeadCnt==6)HttpHeadCnt++; else if(Res==':' && HttpHeadCnt==7)HttpHeadCnt++; else if(Res==' ' && HttpHeadCnt==8)HttpHeadCnt++; else if(HttpHeadCnt>=9 && HttpHeadCnt<=16 )//最大99999999個字節. 16:99999999 17:999999999 18:9999999999 { if(Res!=0x0D) { HttpDataLength = HttpDataLength*10 + Res - '0'; HttpHeadCnt++; } else { HttpDataLengthOK = 1; HttpHeadCnt = 0; } } else { HttpHeadCnt = 0; } } //0D 0A 0D 0A if(HttpHeadOK && HttpDataLengthOK && HttpDataLength && !HttpHeadEndOK) { if(Res==0x0D && HttpHeadCnt==0)HttpHeadCnt++; else if(Res==0x0A && HttpHeadCnt==1)HttpHeadCnt++; else if(Res==0x0D && HttpHeadCnt==2)HttpHeadCnt++; else if(Res==0x0A && HttpHeadCnt==3){HttpHeadEndOK = 1;} else HttpHeadCnt = 0; } if(HttpHeadEndOK == 1)//http數據的head已經過去,后面的是真實數據 { HttpHeadEndOK=0; HttpHeadCnt = 0; HttpDataLengthOK=0; HttpRevDataOK=1;//----------------------------------證明接收到了正確的http數據了------------------------ Usart1ReadCnt=0;//串口從頭開始接收數據,控制串口里面只接收真實數據 } //解析http數據-------------------------------end }