久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 22844|回復(fù): 6
打印 上一主題 下一主題
收起左側(cè)

51單片機實戰(zhàn):物聯(lián)網(wǎng)初步 ESP8266無線網(wǎng)絡(luò)模塊

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:233474 發(fā)表于 2018-4-5 00:31 來自手機 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
前言

扯單一周目BOSS出現(xiàn)!請速速討伐!
ESP8266是我第一個,也是唯一一個接觸過的無線網(wǎng)絡(luò)模塊,我非常喜歡!大部分網(wǎng)上的教程都是ARM架構(gòu)單片機配用ESP8266。我比較摳門,給大家上51版的。
我記得當(dāng)時和老板承諾可以做成無線通信的時候我也不是很確定,心里一直打鼓。好在最后做出來了,很有成就感!所以今天的代碼案例是我把我之前在公司寫的項目代碼簡化之后分享給大家的。雖然結(jié)構(gòu)有點惡心,但應(yīng)該還是入得了眼的。
如果有沒看懂的地方,大家評論區(qū)告訴我。

需求

利用ESP8266芯片,通過無線網(wǎng)絡(luò)同電腦建立TCP連接。接收電腦傳來的消息并顯示在LCD上。

每條信息以\結(jié)尾。
每條信息字符數(shù)不超過32。
信息內(nèi)容只能是ASCII表內(nèi)的字符。
清單

硬件

學(xué)習(xí)板

簡介
由于這次要用到WIFI模塊,沒法用Proteus模擬,所以就上真家伙。
自己焊板子就太麻煩了,所以就買學(xué)習(xí)板(其實我不會焊)。
QX-MINI51

這是我入的學(xué)習(xí)板,你也可以入其他的,如果把握不大就跟我入一樣的。
這個是我在淘寶上小挑了一陣子選的板子:QX-MINI51。尺寸不大不小,想玩的基本都有。配備的單片機是STC89C52。
淘寶鏈接

電路
下面是QX-MINI51在本節(jié)會用到的電路圖
STC89C52

使用89C52芯片,和我們之前用的單片機一樣。
供電&USB串口

CH340芯片是用于普通串口和USB轉(zhuǎn)換的,其上的RXD為串口輸入,TXD為串口輸出。UD+和UD-對應(yīng)USB數(shù)據(jù)線。
雖說是用了USB,其實和普通串口通信線用法一致,只是人家成品方便我們使用封裝成了USB。這里不深究。
流水燈

流水燈在本節(jié)中的角色是輔助調(diào)試(具體的看后面),這里有用的信息就是讓你知道這8個流水燈接哪了。
ESP8266

簡介
主角,簡而言之就是Wi-Fi模塊,屬于網(wǎng)絡(luò)層以上的設(shè)備。擁有MAC地址和IP地址,支持UDP和TCP。
ESP8266

這款的型號是ESP8266-01,其他的和QX-MINI51配合使用不太方便。
淘寶鏈接
參數(shù)
型號        主芯片        無線標(biāo)準(zhǔn)        工作電壓        安全機制        支持模式
ESP8266-01        ESP8266        IEEE 802.11b/g/n        3.3V        WEP/WPA-PSK/WPA2-PSK        STA、AP、STA+AP
STA 模式:ESP8266模塊通過路由器連接互聯(lián)網(wǎng),手機或電腦通過互聯(lián)網(wǎng)實現(xiàn)對設(shè)備的遠(yuǎn)程控制。
AP 模式:ESP8266模塊作為熱點,實現(xiàn)手機或電腦直接與模塊通信,實現(xiàn)局域網(wǎng)無線控制。
STA+AP 模式:兩種模式的共存模式,即可以通過互聯(lián)網(wǎng)控制可實現(xiàn)無縫切換,方便操作。
引腳圖

上圖對8個針腳進行說明。

UTXD        GND        CH_PD        GPIO2        GPIO16        GPIO0        VCC        URXD
發(fā)送        接地        高電平工作        |||電源        接收                        
本例只用到這五個引腳(畫“\”的不用),其他引腳的說明資料請自行到淘寶鏈接處下載。

AT指令
操作ESP8266芯片是靠AT指令的,類似之前的操作LCD1602(《51單片機實戰(zhàn):液晶顯示器のLCD1602》)。操作LCD1602的指令都是一個字節(jié)的十六進制碼,比較難記和理解。AT指令是字符串形式的指令,一般都是單詞縮寫,對可笑的人類比較友好。
之前和LCD1602交互是靠并口傳輸,而這次是用串口傳輸(串口傳輸簡例:《51單片機實戰(zhàn):與計算機異步串行通信》),所以這次的Wi-Fi通信是建立在串口通信基礎(chǔ)上的。

AT指令集下載鏈接
AT指令使用示例下載鏈接

波特率
注意,這個模塊的默認(rèn)波特率是115200,本例也是根據(jù)這個波特率進行演示的。若想改變波特率請使用以下語句進行修改:

AT+CIOBAUD=<baudrate>,<databits>,<stopbits>,<parity>,<flow control>
如:

AT+CIOBAUD=9600,8,1,0,0  
軟件

程序        說明        下載
UartAssist        串口調(diào)試助手,用來給單片機發(fā)送消息        度娘網(wǎng)盤
NetAssist        網(wǎng)絡(luò)調(diào)試助手,在電腦端建立TCP連接與單片機的ESP8266進行通信        度娘網(wǎng)盤
STC-ISP        STC單片機工具集,很強大,可燒錄程序,可串口調(diào)試等等        度娘網(wǎng)盤
CH340驅(qū)動        CH340的USB驅(qū)動,如果沒有這個驅(qū)動,你的電腦可能識別不到單片機(識別到CH340就相當(dāng)于識別到單片機的串口。)        度娘網(wǎng)盤
51單片機波特率初值計算工具        用于計算在各種波特率和晶振頻率等參數(shù)下計時器的初值,屬于輔助工具,省的還得算。        度娘網(wǎng)盤
分析

調(diào)試

在開始用單片機直接和無線模塊通信之前,首先要繞過單片機直接和無線模塊通信以確定其可以使用和接入默認(rèn)網(wǎng)絡(luò)(接入一個熱點后,模塊每次斷電后啟動都會自動連接該熱點),這樣可以讓單片機少做很多事情(要知道我們用的是51單片機,硬件資源極其有限,能省則省)。

TXD/RXD反接
首先要繞過單片機直接給ESP8266下指令,就要用電腦的串口。但ESP-01是針腳接口,所以我們可以利用QX-MINI51上的針腳和USB接口。

回看前面QX-MINI51的主控芯片和USB的電路圖,可以發(fā)現(xiàn),單片機的串口引腳是被并聯(lián)式的暴露再外的,分別為:P30 - P31和USB,前者為針腳接口,后者為USB接口。且它們的RXD和TXD的數(shù)據(jù)信息是一摸一樣的,注意并不是兩個獨立的串口,是同一個串口。比方說,單片機要往出發(fā)送一個1,P30針腳和USB都會是往出發(fā)送一個1。

所以我們利用這個特點,將ESP8266的TXD接到P31(單片機的TXD),RXD接到P30(單片機的RXD),這樣就等于讓ESP8266直接和USB打交道,也就是和電腦直接打交道了。

為什么叫反接,我一般管RXD對TXD叫正接。嗯…
接線圖

強勢秀一波畫工!
我覺得應(yīng)該可以看得懂吧,ESP8266的引腳說明請看前面的引腳圖?醇t色號碼對應(yīng)接線,其中4、5、6號引腳不用。
實物圖

這個圖就很難看出線是怎么連的了,所以你要忍受我丑陋的畫工。

接入網(wǎng)絡(luò)
打開串口調(diào)試助手,調(diào)好參數(shù)
串口調(diào)試助手,設(shè)置參數(shù)

其中串口號你連的哪個串口就設(shè)置哪個串口號,我是連的COM3。
另一個要注意的就是波特率要115200(ESP-01的默認(rèn)波特率,也可以統(tǒng)一改為9600)。
打開串口后,給開發(fā)板上電。你的串口調(diào)試助手會有信息出來(文本顯示,不要十六進制顯示)。
?諄MEM CHECK FAIL!!!
d{$弬s
Ai-Thinker Technology Co. Ltd.

invalid
顯示的信息類似上面,你可以先給個測試命令A(yù)T看看是否可以接受指令

注意!每個指令后要跟回車再發(fā)送!
如果返回OK則說明指令可以被接收并識別。

如果下面的指令都會返回ERROR(在沒有給錯指令的情況下),可以嘗試AT+RST重啟模塊。

1. 更改模式
指令:AT+CWMODE?
一般情況下,第一次使用會返回2,也就是AP模式,我們不用它發(fā)熱點,所以要改回Station模式(模式1)。

指令:AT+CWMODE?
一般情況下,第一次使用會返回2,也就是AP模式,我們不用它發(fā)熱點,所以要改回Station模式(模式1)。

指令:AT+CWMODE=1
返回:OK則成功

2. 接入熱點(連Wi-Fi)
指令:AT+CWJAP=<SSID>,<Password>
參數(shù):<SSID>處填寫熱點名稱,<Password>處填寫密碼。兩者都要用雙引號括起來。
例如:AT+CWJAP="CMCC","123456"

指令:AT+CWJAP=<SSID>,<Password>
參數(shù):<SSID>處填寫熱點名稱,<Password>處填寫密碼。兩者都要用雙引號括起來。
例如:AT+CWJAP="CMCC","123456"

返回:WIFI CONNECTED:連接到熱點
返回:WIFI GOT IP:分配到IP,走到這一步,就算已經(jīng)連入到熱點了。

如果忘記SSID了,想看一下可以使用下面的指令,列出廣播的SSID(隱藏的不會顯示)。
指令:AT+CWLAP

3. 連接TCP服務(wù)器
首先打開NetAssist,設(shè)置TCP Server,然后建立連接(注意防火墻)。注意,Server必須在Client所在內(nèi)網(wǎng)或其外網(wǎng)(我的是在同一個內(nèi)網(wǎng))。
網(wǎng)絡(luò)調(diào)試助手
首先打開NetAssist,設(shè)置TCP Server,然后建立連接(注意防火墻)。注意,Server必須在Client所在內(nèi)網(wǎng)或其外網(wǎng)(我的是在同一個內(nèi)網(wǎng))。


網(wǎng)絡(luò)調(diào)試助手
指令:AT+CIPSTART=<Type>,<DomainName>,<Port>
參數(shù):<Type>處寫TCP或UDP,<DomainName>處寫域名,<Port>處寫端口號。
本例:AT+CIPSTART="TCP","192.168.1.110",1234
返回:

CONNECT

OK
說明連接成功。
在NetAssist中,數(shù)據(jù)接收框的下面有一個連接對象,點開后發(fā)現(xiàn)除了All Connections之外,多了一個客戶,就確定客戶連接到服務(wù)器了。
NetAssist

在下方文本框輸入信息后發(fā)送,可在串口調(diào)試助手中看到ESP8266所接收到的信息
UartAssist收到的信息:+IPD,10:Hello 簡書
到這里就說明網(wǎng)絡(luò)連接及建立TCP都可以順利完成,在下面的單片機操作中就會變得方便很多。

注意,ESP8266每次斷電后重新上電,最多只會自動連到之前連接的熱點,但不會自動連接到TCP服務(wù)器,所以,建立連接要交給單片機來做。
問題

波特率
本例要使用的波特率為115200的,不是9600。引申出來的問題就是:算初值(方法詳見:《51單片機實戰(zhàn):與計算機異步串行通信》 - 知識點 - 波特率 - 溢出率)。
手算真的很麻煩,因為在參數(shù)固定的情況下,算起來已經(jīng)很煩了,更何況那些參數(shù)可能還會變得情況。
所以上神器:
初值計算器
反饋及識別
我們要做的是讓單片機在收到ESP8266回饋的WIFI GOT IP后發(fā)出連接TCP服務(wù)器的指令。
發(fā)送指令不用多說,只要記得在后面跟"換行(CR)"和"新行(NL)"字符就行(這兩個是不一樣的)。
1. 關(guān)鍵字符配對
如果是電腦程序的高級語言編程,這個問題就不存在了。但是我們給單片機寫程序就要牢記它的一些點(《扯會兒單片機開發(fā):開始》),比如硬件資源十分緊張。
一個是因為它存儲空間很小,另一個是因為晶振太慢,所以我們要想辦法縮減配對時間。因為單片機的使用往往很單一,所以策略都是根據(jù)情況來設(shè)定的。比如本例,單片機接收的回饋無非那么幾種,所以我制定的策略就是關(guān)鍵字符配對。

比如識別WIFI GOT IP,我只是別第一個字符W和第6個字符G,就說明我收到的就是這個回饋信息。如果收到第一個是W,只有這條指令的第六個字符是G,所以就可以確定。如果是出現(xiàn)干擾,可能性也是比較低的,我們的交互是在網(wǎng)絡(luò)層的,下層也可以把出錯的報文擋掉。

總體來說還是蠻可靠的,如果你有更棒的方法,請在評論區(qū)告訴我,大家一起學(xué)習(xí)進步。

2. 利用流水燈
上面就是理論工作,已經(jīng)做得7788了。但實際經(jīng)驗告訴我,如果的代碼哪里也出岔子了在51單片機開發(fā)中真的比較難發(fā)現(xiàn),他不像高級程序語言可以報錯,可以try - catch。但這個就別想了,所以我們要自己想辦法,讓他可以反饋我們的程序至少是正常運行的,這樣可以節(jié)省很多時間。

我在這里介紹的我的方法是利用LED,或成組的流水燈(更好)。承租的流水燈一般是8個,可以直接顯示一個字節(jié)的信息,可能有人問為什么不用LCD?你若會LCD或者看過《51單片機實戰(zhàn):液晶顯示器のLCD1602》就會發(fā)現(xiàn),LCD本身的開發(fā)就有點復(fù)雜了。你很難保證這個子程序運行正常,更別提用它抓錯了。只能是不推薦哈,我覺得不可靠。LED的話就很簡單了,就是個關(guān)開,一般不會出錯。

QX-MINI51開發(fā)板上自帶流水燈,你要是入的其他開發(fā)板,一般都是有的。如果沒有,就單買LED回來(如果不知道去哪買,鏈接)。

我一般會怎么做呢,先讓流水燈直接顯示串口接收的數(shù)據(jù),為了知道我們至少是能接收到東西的。然后利用上面的關(guān)鍵字符識別,收到WIFI CONNECTED亮一號燈,收到WIFI GOT IP亮二號燈,收到CONNECT OK亮三號燈。這樣,根據(jù)燈亮滅的情況就能確定哪一步出了問題,然后定位到代碼或者設(shè)置。

還是那句話,如果你有更棒的方法,歡迎在評論區(qū)交流。

到這里就做完了所有理論上的準(zhǔn)備工作,也就是理論上我們已經(jīng)可以實現(xiàn)這個程序了,下面代碼實現(xiàn)。

代碼

說下這次代碼比較新穎的地方,一個是用到了.c和.h文件組合的模塊形式,另一個是用到了函數(shù)指針(函數(shù)名也被括起來的那個)。前者這種寫法是為了將各子功能模塊化,.h文件里的內(nèi)容相當(dāng)于面向?qū)ο缶幊汤锏膒ublic,.c文件一個是實現(xiàn).h內(nèi)的函數(shù),另一個就是隱藏函數(shù)和變量,相當(dāng)于private。后者是用來充當(dāng)高級語言中的“事件”,讓函數(shù)調(diào)用變得更加靈活,其具體用法請自己查資料或者看相關(guān)C語言書籍。

總而言之,這次的代碼是模塊化和事件化的,類似面向?qū)ο蟮木幋a風(fēng)格。
準(zhǔn)備
因為用于通訊,所以我把ASCII內(nèi)所有的特殊字符都寫到一個頭文件里。雖然本例只用到其中的幾個,但以后重復(fù)利用這個頭文件。

ASCII.h

#ifndef __ASCIIS__
#define __ASCIIS__

#define NUL 0x00 // NULL
#define SOH 0x01 // Start of Heading
#define STX 0x02 // Start of Text
#define ETX 0x03 // End of Text
#define EOT 0x04 // End of Transmission
#define ENQ 0x05 // Enquiry
#define ACK 0x06 // Acknowledge
#define BEL 0x07 // Bell
#define BS 0x08 // Backspace
#define HT 0x09 // Horizontal Tab
#define LF 0x0A // Line Feed
#define NL 0x0A // New Line
#define VT 0x0B // Vertical Tab
#define FF 0x0C // Form Feed
#define NP 0x0C // New Page
#define CR 0x0D // Carriage Return
#define SO 0x0E // Shift Out
#define SI 0x0F // Shift In
#define DLE 0x10 // Data Link Escape
#define DC1 0x11 // Device Control 1
#define DC2 0x12 // Device Control 2
#define DC3 0x13 // Device Control 3
#define DC4 0x14 // Device Control 4
#define NAK 0x15 // Negative Acknowledge
#define SYN 0x16 // Synchronous Idle
#define ETB 0x17 // End of Transmission Block
#define CAN 0x18 // Cancel
#define EM 0x19 // End of Medium
#define SUB 0x1A // Substitute
#define ESC 0x1B // Escape
#define FS 0x1C // File Separator
#define GS 0x1D // Group Separator
#define RS 0x1E // Record Separator
#define US 0x1F // Unit Separator
#define SP 0x20 // Space

#endif
LCD
這里都是關(guān)于LCD1602顯示器的主要代碼,與文章《51單片機實戰(zhàn):液晶顯示器のLCD1602》所講的一樣,這里就不給出注釋了。
lcd1602.h

#ifndef __LCD1602__
#define __LCD1602__

typedef bit BOOL;

void LCD_writeCmd(unsigned char cmd);  //寫命令
void LCD_writeData(unsigned char dat);  //寫數(shù)據(jù)
void LCD_writeLine(unsigned char *line);  //寫行數(shù)據(jù)
void LCD_init();  //初始化
void delay(unsigned int z);  //粗略的延時器

#endif
lcd1602.c

#include <reg52.h>
#include "lcd1602.h"

#define LCD_CLEAR 0x01
#define LCD_Display_Mode 0X38

#define DISPLAY_OFF 0x08
#define DISPLAY_ON_NO_CURSOR 0x0c
#define DISPLAY_ON_WITH_CURSOR_NO_BLINK 0x0e
#define DISPLAY_ON_WITH_CURSOR_BLINK 0x0f

#define AUTO_BACK_STEP 0x04
#define AUTO_NEXT_STEP 0x06
#define AUTO_DISPLAY_MOVE_LEFT 0x07
#define AUTO_DISPLAY_MOVE_RIGHT 0x05

#define ALL_MOVE_LEFT 0x18
#define ALL_MOVE_RIGHT 0x1c
#define CURSOR_MOVE_LEFT 0x10
#define CURSOR_MOVE_RIGHT 0x14

#define FIRST_ROW 0x80
#define SECOND_ROW FIRST_ROW+0x40

sbit enable = P0^5;
sbit RS = P0^7;
sbit RW = P0^6;

void delay(unsigned int z)
{
    unsigned int x,y;
    for(x=z;x>0;x--)
        for(y=220;y>0;y--);
}

void LCD_writeCmd(unsigned char cmd){
    RS = 0;
    P2 = cmd;
    delay(5);
    enable = 1;
    delay(5);
    enable = 0;
}

void LCD_writeData(unsigned char dat)
{
    RS = 1;
    P2 = dat;
    delay(5);
    enable = 1;
    delay(5);
    enable = 0;
}

void LCD_writeLine(unsigned char *line){
    unsigned char i=0;
    BOOL flag = 0;
    LCD_writeCmd(LCD_CLEAR);  //每次送來信息都清屏,可以一直刷新顯示送來的信息。
    LCD_writeCmd(FIRST_ROW);
    while(line[ i] != '\0'){
        LCD_writeData(line[i++]);
        if(i>15 && flag == 0){
            LCD_writeCmd(SECOND_ROW);
            flag = 1;
        }
        delay(5);
    }
}

void LCD_init()
{
    RW = 0;
    enable = 0;
    LCD_writeCmd(LCD_Display_Mode);
    LCD_writeCmd(DISPLAY_ON_NO_CURSOR);
    LCD_writeCmd(AUTO_NEXT_STEP);
    LCD_writeCmd(LCD_CLEAR);
}
串口通信
這里用于單片機和ESP8266交互,與文章《51單片機實戰(zhàn):與計算機異步串行通信》相似。其中的不同點前面已經(jīng)說過。
stc52ser.h

#ifndef __STC52_SER__
#define __STC52_SER__

extern void (*SerialPort_Event_ByteReceived)(unsigned char byte);  //事件:串口接收到字節(jié)

void SerialPort_Init_Low();  //初始化為11.0592MHz下的9600波特率
void SerialPort_Init_High();  //初始化為22.1184下的115200波特率
void SerialPort_SendByte(unsigned char byte);  //發(fā)送一個字節(jié)
void SerialPort_SendData(unsigned char* bytes);  //發(fā)送一組字節(jié)

#endif
stc52ser.c

#include <reg52.h>
#include "ASCIIS.h"
#include "stc52ser.h"

//Byte Received Event
void (*SerialPort_Event_ByteReceived)(unsigned char byte);

//initialize registers pertinent to serial port
void SerialPort_Init_Low(){
    //set and run Timer1
    //mode2: 8bit, auto reload initial value
    //9600bps and 11.0592MHz => 0xfd(initial value)
    TMOD = 0x20;
    TH1 = 0xfd;
    TL1 = 0xfd;
    TR1 = 1;
   
    //set serial port configuration and enable receive
    //mode1: asyc 10bit(8 data bit), alterable baud rate
    SM0 = 0;
    SM1 = 1;
    REN = 1;
   
    //set interruption
    //enable all and serial port interruption
    EA = 1;
    ES = 1;
}

//initialize registers pertinent to serial port for esp8266
void SerialPort_Init_High(){
    //SMOD = 1
    PCON |= 0x80;
   
    //set and run Timer1
    //mode2: 8bit, auto reload initial value
    //115200bps and 22.1184MHz => 0xfd(initial value)
    TMOD = 0x20;
    TH1 = 0xff;
    TL1 = 0xff;
    TR1 = 1;
   
    //set serial port configuration and enable receive
    //mode1: asyc 10bit(8 data bit), alterable baud rate
    SM0 = 0;
    SM1 = 1;
    REN = 1;
   
    //set interruption
    //enable all and serial port interruption
    EA = 1;
    ES = 1;
}

//Send a byte
void SerialPort_SendByte(unsigned char byte){
    ES = 0;
    SBUF = byte;
    while(!TI);
    // transmit interrupt
    TI = 0;
    ES = 1;
}

//Send a data of byte sequence end by 'EOT'
void SerialPort_SendData(unsigned char* bytes){
    int i = 0;
    while(bytes[ i] != EOT){
        SerialPort_SendByte(bytes[ i]);
        i++;
    }
}


//Occured when byte received
void receivedInterruped() interrupt 4 {
    TR0 = 0;
    (*SerialPort_Event_ByteReceived)(SBUF);
    while(!RI);
    RI = 0;
}
簡單說一下,這里留了兩個初始化函數(shù),SerialPort_Init_Low()用于11.0592MHz下的9600波特率,SerialPort_Init_High()用于22.1184MHz下的115200波特率(此例用這個)。這樣寫只是為了以后可以重用(軟工狗的矯情)。

無線
這里是最主要的代碼,都是關(guān)于ESP8266的,也是作為一個模塊給主函數(shù)調(diào)用。
esp8266.h

#ifndef __ESP8266__
#define __ESP8266__

extern void (*ESP01_Event_WifiConnected)();    //事件:Wi-Fi已連接
extern void (*ESP01_Event_IpGot)();    //事件:IP地址已獲得
extern void (*ESP01_Event_TcpServerConnected)();    //事件:已連接到TCP服務(wù)器
extern void (*ESP01_Event_MsgReceived)(unsigned char* head);    //事件:已獲得消息,head為消息數(shù)組頭

void ESP01_Init();  //無線模塊初始化
void ESP01_ConnectToTCPServer();  //連接TCP服務(wù)器

#endif
esp8266.c

#include <reg52.h>
#include "stc52ser.h"
#include "ASCIIS.h"
#include "esp8266.h"

#define BUFFER_MAX_SIZE 99  //緩沖區(qū)大小
unsigned char buffer[BUFFER_MAX_SIZE];  //緩沖區(qū):用于存放從ESP8266接收來的各種信息

//連接到TCP服務(wù)器的指令:AT+CIPSTART="TCP","192.168.1.110",1234。后面的CR和NL是AT指令的固定結(jié)尾,EOT用于SerialPort_SendData發(fā)送時識別結(jié)尾。
code unsigned char cmd_connectToTCPServer[] = {0x41, 0x54, 0x2B, 0x43, 0x49, 0x50, 0x53, 0x54, 0x41, 0x52, 0x54, 0x3D, 0x22, 0x54, 0x43, 0x50, 0x22, 0x2C, 0x22, 0x31, 0x39, 0x32, 0x2E, 0x31, 0x36, 0x38, 0x2E, 0x31, 0x2E, 0x31, 0x31, 0x30, 0x22, 0x2C, 0x31, 0x32, 0x33, 0x34, CR, NL, EOT};
int counter = 0;    //用于ESP8266的執(zhí)行步驟計數(shù)
int writeIndex = 0;    //緩沖區(qū)寫索引

void (*ESP01_Event_WifiConnected)();
void (*ESP01_Event_IpGot)();
void (*ESP01_Event_TcpServerConnected)();
void (*ESP01_Event_MsgReceived)(unsigned char* head);

//注意:下面代碼推薦從后往前看,從注釋標(biāo)"1. "處開始。

void prepareForData(unsigned char byte);    //因為第四步和第三步會相互調(diào)用,所以這里只是做了個聲明(C語言的矯情點)。

//4. 將信息插入到緩沖區(qū)并送給單片機。
void insertDataIntoBuffer(unsigned char byte){
    if(byte == '\\'){
        //檢測到'\'后,將信息送出到單片機
        buffer[writeIndex] = '\0';
        (*ESP01_Event_MsgReceived)(buffer);
        SerialPort_Event_ByteReceived = &prepareForData;    //回到第三步,準(zhǔn)備接收下一條信息
        writeIndex = 0;
        return;
    }
    buffer[writeIndex++] = byte;
}

//3. 準(zhǔn)備信息:這里是過度步驟,前面可以觀察到,ESP8266在接收發(fā)來的信息時是有個頭的,這里的作用就是去頭。
void prepareForData(unsigned char byte){
    if(byte == ':'){
        SerialPort_Event_ByteReceived = &insertDataIntoBuffer;
        writeIndex = 0;
    }
}

//識別回饋指令:用于識別接收到的是WIFI CONNECTED(連上熱點)還是WIFI IP GOT(獲得IP)還是CONNECT(連上TCP服務(wù)器)
void parseCmd(){
    switch(counter){
        case 1:
            if(buffer[0] == 'W' && buffer[5] == 'C'){
                (*ESP01_Event_WifiConnected)();
                counter += 1;
            }
            break;
        case 2:
            if(buffer[0] == 'W' && buffer[5] == 'G'){
                (*ESP01_Event_IpGot)();
                counter += 1;
            }
            break;
        case 3:
            if(buffer[0] == 'A' && buffer[3] == 'C')
                counter += 1;
            break;
        case 4:
            if(buffer[0] == 'C' && buffer[3] == 'N' && buffer[6] == 'T'){
                (*ESP01_Event_TcpServerConnected)();
                SerialPort_Event_ByteReceived = &prepareForData;  //連接到TCP服務(wù)器后,進入第三步。
            }
    }
}

//2. 這里開始向緩沖區(qū)存儲信息,用于識別。
void insertBuffer(unsigned char byte){
    if(byte == NL){
        //收到尾(NL)后,將緩沖區(qū)的回饋信息送去識別
        parseCmd();
        writeIndex = 0;
        return;
    }
    buffer[writeIndex++] = byte;
}

//1. 接收頭:頭是無用信息,但我們要通過頭里面的一些字符,推算出什么時候到達第二步(WIFI CONNECTED)
void headerReceived(unsigned char byte){
    if(byte == NL){
        //頭內(nèi)有5個NL,只要數(shù)夠5個,下一個就是第二步的內(nèi)容了。
        if(++counter == 5){
            SerialPort_Event_ByteReceived = &insertBuffer;  //跳到第二步
            counter = 1;
        }
    }
}

//同.h中的聲明
void ESP01_Init(){
    SerialPort_Init_High();
    SerialPort_Event_ByteReceived = &headerReceived;  //事件注冊
}

//同.h中的聲明
void ESP01_ConnectToTCPServer(){
    SerialPort_SendData(cmd_connectToTCPServer);
}
主函數(shù)
main.c

#include <reg52.h>
#include "lcd1602.h"
#include "esp8266.h"

//連接到Wi-Fi后,亮第一個燈
void EventHandler_WifiConnected(){
    P1 &= 0xFE;
}

//獲得IP后,亮第二個燈
void EventHandler_IpGot(){
    P1 &= 0xFD;
    ESP01_ConnectToTCPServer();
}

//連接到TCP服務(wù)器后,亮第三個燈
void EventHandler_TcpServerConnected(){
    P1 &= 0xFB;
}

//將ESP8266送來的信息,送去LCD顯示。
void EventHandler_MsgReceived(unsigned char* head){
    LCD_writeLine(head);
}

//初始化
void init(){
    ESP01_Event_WifiConnected = &EventHandler_WifiConnected;  //事件注冊
    ESP01_Event_IpGot = &EventHandler_IpGot;  //事件注冊
    ESP01_Event_TcpServerConnected = &EventHandler_TcpServerConnected;  //事件注冊
    ESP01_Event_MsgReceived = &EventHandler_MsgReceived;  //事件注冊
    ESP01_Init();
    LCD_init();
}

void main(){
    init();
    while(1);
}
編譯
編譯前要設(shè)置一下目標(biāo)參數(shù),如下圖。
目標(biāo)設(shè)置

注意這里要改成XDATA,不然編譯通不過的。
效果

開始前請確定在同一個網(wǎng)絡(luò)下,并且服務(wù)端已開啟。

初始化效果

我只是把單片機連到移動電源上了。

服務(wù)端

為了能讓1602第一行顯示Hello,第二行顯示W(wǎng)orld,中間可以留了11個空格。
客戶端
結(jié)語

猴!到這里這個程序就算完成了。這個比那些用手機控制開關(guān)燈要復(fù)雜一些。所以你只要掌握了這個例子,那些都不在話下了

作者:兔子澤
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。

評分

參與人數(shù) 2黑幣 +51 收起 理由
ontheroad + 1 很給力!
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏4 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:302267 發(fā)表于 2018-4-5 08:23 | 只看該作者
贊一個,寫的真棒,繼續(xù)學(xué)習(xí)。
回復(fù)

使用道具 舉報

板凳
ID:88606 發(fā)表于 2018-4-5 08:43 | 只看該作者
樓主,你發(fā)的圖片在哪?
回復(fù)

使用道具 舉報

地板
ID:374872 發(fā)表于 2018-8-24 09:28 | 只看該作者
謝謝分享,不過圖呢
回復(fù)

使用道具 舉報

5#
ID:137767 發(fā)表于 2018-8-26 06:49 | 只看該作者
夏凌霄927 發(fā)表于 2018-8-24 09:28
謝謝分享,不過圖呢

我找到帶圖的。不知是不是一人創(chuàng)作。    https://www.jianshu.com/p/f95441572a31

評分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 回帖助人的獎勵!

查看全部評分

回復(fù)

使用道具 舉報

6#
ID:20672 發(fā)表于 2018-12-22 14:05 | 只看該作者
謝謝分享
回復(fù)

使用道具 舉報

7#
ID:445069 發(fā)表于 2019-1-18 09:15 | 只看該作者
單片機連接無線模塊是必需的,這樣才能提高單片機的通信能力,向物聯(lián)網(wǎng)靠近。
如果還是依靠串口,就無法擺脫對PC的依賴,推廣的成本太高了。
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 亚洲一区二区在线播放 | 91毛片在线看 | 黄色永久免费 | 成人欧美一区二区三区黑人孕妇 | 美女视频.| pacopacomama在线 | 欧美日韩高清 | 欧美三区视频 | 日韩性在线 | 最新国产在线 | 亚洲成人中文字幕 | 日韩视频一区二区 | 国产日韩欧美一区二区 | 99精品免费在线观看 | 麻豆av网站 | 日韩视频免费 | 人人干免费| 国产传媒在线观看 | 国产成人一区二区三区 | a在线视频| 中文字幕亚洲无线 | 黄色大片在线视频 | 久草99 | 日日操日日干 | 国产一区二区三区在线 | 亚洲激情综合网 | www亚洲精品| 国产精品不卡一区 | 国产成人免费一区二区60岁 | 黄色在线免费网站 | 99久久国产综合精品麻豆 | 亚洲视频精品 | 欧美嘿咻 | 欧美福利久久 | 久久久精品一区 | 国产精品片| 久久精品久久久 | av中文天堂 | 日韩美女在线看免费观看 | 久久区二区 | 免费的日批视频 |