在嵌入式開發中,無線通信的方式有很多,其中 WIFI 是繞不開的話題。說到 WIFI 通信,就不得不提 ESP8266了。
ESP8266 是一款高性能的 WIFI 串口模塊,實現透明傳輸。只要有一定的串口知識,不需要知道 WIFI 原理就可以上手,在業內應用廣泛。
1. 源碼下載
本文首發 良許嵌入式網 :https://www.lxlinux.net/e/ ,歡迎關注!
本文所涉及的源碼及安裝包如下(由于平臺限制,請點擊以下鏈接閱讀原文下載):
https://www.lxlinux.net/e/stm32/esp8266-tutorial.html
STM32F103C8T6模板工程
本文的源碼
串口調試助手
網絡調試助手
CH340驅動
如果不知道如何搭建 STM32 編程環境,不知道如何燒錄 STM32 代碼,可以閱讀這篇文章:
https://www.lxlinux.net/e/stm32/stm32-quick-start-for-beginner.html
如果你連代碼都不知道怎么燒錄到 STM32 的,可以參考下文,提供了 5 種代碼燒錄方式:
https://www.lxlinux.net/e/stm32/five-ways-to-flash-program-to-stm32.html
文中所使用的芯片是 STM32F103C8T6 ,配套了一個工程模板,如果你需要自己搭建一個工程模板,可以參考下文:
https://www.lxlinux.net/e/stm32/create-stm32-hal-project-template.html
2. ESP8266介紹
ESP8266 是一個非常強大的 WIFI 模塊,可以利用串口與單片機進行通訊,從而編程實現控制 ESP8266。利用 ESP8266 可以訪問一些 API,獲取天氣信息或者完成網絡授時,也可以連接云平臺進行開發。不過因為是串口傳輸,速度較慢,不能用來傳輸圖像、視頻這些大容量的數據,但是傳些傳感器數據還是綽綽有余的。
我們常說的 ESP8266 是指 ESP8266 WIFI 模塊,它是物聯網和嵌入式開發常用的模塊,其中 ESP8266 是 WIFI 模塊的芯片型號。
ESP8266 有 ESP-01/01S/07/07S/12E/12F/12S 等規格,還有正點原子自研的 ATK-ESP8266 (修改了固件及模組引腳)。
本文用到的是 ESP-01S,長下面這樣。這種模組非常便宜,某寶幾塊錢一個,建議可以買幾個囤著。
3. 三種調試方式
ESP8266 已經是一款很成熟的模組了,前文提到,它可以通過串口進行通訊。
既然可以進行串口通訊,那么我們就可以使用以下三種方法進行調試。
- USB 轉 TTL 工具
這玩意兒大家應該非常熟悉了,通常我們用它來打印單片機 log。
當然,配合上位機(比如串口調試助手),我們也可以使用它對一些模組進行調試,比如:ESP8266、4G模組、藍牙,等等。
如果對這個工具使用不熟悉的小伙伴,可以閱讀下文:
【零基礎快速上手STM32開發(手把手保姆級教程)】
USB轉TTL模塊 | ESP8266 |
---|---|
3.3V | 3.3V |
TXD | RX |
RXD | TX |
GND | GND |
使用 USB 轉 TTL 工具調試 ESP8266,可以通過上面的表格進行接線。
3.3V 相接后可能無法啟動 ESP8266,這是因為 USB 轉 TTL 模組的 3.3V 并沒有真的達到 3.3V,莫慌,直接將 ESP8266 的3.3V 引腳接入 USB 轉 TTL 的 5V 引腳,如果 ESP8266 會發燙到無法觸摸就拔掉,如果溫度你手指還能接受,那就沒問題,ESP8266 還是沒那么脆弱的。
接好線之后,將 USB 端連接到電腦,打開串口調試助手就可以進行調試了。
- USB 轉 ESP8266WIFI 模塊

上面的 USB 轉 TTL 模組需要你動手去接線,比較麻煩,而且要是線有一根接錯了,就無法正常調試了。
而這個模組專門是為了調試 ESP8266 而設計,不需要一個個引腳接線,直接把 ESP8266 往上一插就可以啦,超方便的。同樣,USB 端連接電腦,打開串口調試助手就可以進行調試了。
- 單片機調試
這種就是在項目中最常用的方式了。需要將 ESP8266 接到單片機的任意一個串口,然后再編寫代碼驅動 ESP8266 ,實現各種業務邏輯。
本文就是手把手教大家編寫一個 ESP8266 驅動程序。
上電:正常工作驗證
模塊拿到手之后,我們需要先確保這個模組是正常的,否則后面的調試、寫代碼都是白搭。
首先,上電后,藍色燈微弱閃爍后熄滅,表示正常工作。

還可以更進一步,接好線之后,然后打開串口調試助手發送 AT(并且還要敲一個回車),ESP8266 回復 OK,就是正常啟動了。
4. ESP8266工作模式
ESP8266 支持 STA、AP、AP+STA 三種工作模式。
- STA 模式(Station)
一般用于遠距離傳輸。ESP8266 通過路由器連接互聯網,終端設備通過互聯網實現對設備的遠程控制。簡單來說,此時的 ESP8266 可以當作是一個客戶端,可以向服務端進行數據的下載與傳輸。這就類似于,手機/平板/筆記本(客戶端)可以通過 WIFI 連接到路由器進行上網。
- AP 模式(Access Point)
一般用于近距離傳輸。ESP8266 作為熱點,提供無線接入服務、數據訪問,一般的無線路由/網橋工作在 AP 模式下,最多支持 4 臺設備接入。簡單來說,此時的 ESP8266 可以當作是一個服務端。這就類似于,ESP8266 變身為一個路由器,然后手機/平板/筆記本可以通過 WIFI 連接到 ESP8266 進行上網。
- AP+STA 模式
兩種模式的共存模式,可以通過互聯網控制可實現無縫切換,方便操作。簡單來說,此時的 ESP8266 可以當作是一個路由器既可以做服務端接收也可以當客戶端連接路由器,進行聯網傳輸和控制。
5. AT指令介紹
5.1 什么是AT指令?
AT 指令(AT Commands)最早是由發明撥號調制解調器的賀氏公司為了控制撥號調制解調器而發明的控制協議。后來隨著網絡帶寬的升級,速度很低的撥號調制解調器基本退出市場,但是 AT 指令被保留了下來。
在嵌入式開發中,經常是使用 AT 命令去控制各種通訊模塊,比如 ESP8266 模塊、4G 模塊、GPRS 模塊等等。一般就是主芯片通過硬件接口(比如串口、SPI)發送 AT 指令給通訊模塊,模塊接收到數據之后回應響應的數據。
5.2 常用AT指令介紹
AT 指令分為四種類型:
類型 | 格式 | 功能 |
---|---|---|
測試指令 | AT + < X > = ? | 查詢設置命令或內部程序設置的參數及其取值范圍 |
查詢指令 | AT + < X > ? | 返回參數的當前值 |
設置指令 | AT + < X > = < ... > | 設置用戶自定義的參數值 |
執行指令 | AT + < X > | 執行受模塊內部程序控制的變參數不可變 |
AT 指令有近百條,但常用的就十幾條,理解起來也非常簡單,現在舉例一些常用指令,并使用這些指令一步一步的通過 TCP 連接到遠程的服務器實現收發數據。
AT指令 | 功能 |
---|---|
AT | 測試是否正常啟動 |
AT+CWMODE=1 | 設置 STA 模式 |
AT+CWMODE=2 | 設置 AP 模式 |
AT+CWMODE=3 | 設置 AP+STA 模式 |
AT+RST | 重啟生效 |
AT+CWSAP=”SSID”,”password”,1,4 | 設置 AP 參數:賬號為SSID ,密碼為password,通道號為 1,加密方式為:WPA_WPA2_PSK |
AT+CIPMUX=0 | 開啟單連接 |
AT+CIPMUX=1 | 開啟多連接 |
AT+CIPSERVER=1,8080 | 開啟 SERVER 模式,設置端口為 8080 |
AT+CIPSTART=“TCP”,"192.168.X.XXX”,8080 | 建立 TCP 連接到”192.168.X.XXX”,8080 |
AT+CIPSTART=“UDP”,“192.168.X.XXX”,8080 | 建立 UDP 連接到”192.168.X.XXX”,8080 |
AT+CIPCLOSE | 斷開 TCP 連接 |
AT+CWQAP | 斷開熱點 |
AT+CIPSEND=n | 開始傳輸,n表示需要傳輸的字節數 |
AT+CIPSEND=0,n | 向 ID0 發送 n 字節數據包,n的值自己定 |
AT+CIPMODE=1 | 開啟透傳模式 |
AT+CIPSEND | 開始發送數據 |
AT+CIPMODE=0 | 退出透傳 |
AT+CWJAP="SSID,“password” | 加入 WIFI 熱點:SSID ,密碼為:password |
AT+CIFSR | 查詢 ESP8266 的 IP 地址 |
AT+CIPSTA? | 查詢 ESP8266 的 IP 、網關地址和子網掩碼 |
接下來我們要用串口助手發送 AT 指令,如果你還不會用串口助手,那么動動小手跟我操作:
- 插上 USB,選擇正確的串口號,正確的串口號是插上 USB 后多出的串口號;
- 選擇波特率,ESP8266 默認波特率是 115200 ,可以通過 AT 指令修改;
- 點擊「打開」或者「打開串口」;
- 在輸入框輸入指令,AT 指令要以回車結尾;
- 點擊「發送」,觀察 ESP8266 的返回值;
- 使用完點「斷開」或者「關閉串口」。
不一定要用我的串口助手,別的串口助手也可以(比如正點原子開發的串口助手,甚至你自己寫一個也行),都是一樣的。
如果已經插上 USB,選擇了正確的串口號,但是出現串口打不開并輸出「【ERROR】Cannot set COM port parameters」 的情況,可能是 CH340 驅動還沒安裝,或者需要卸載重新安裝一下。教你解決:
- 先點「斷開」,斷開串口;
- 打開 CH340 驅動安裝程序,我文章開頭有提供;
- 如果你沒有安裝過,點擊「安裝」;如果你安裝過,點擊「卸載」再點擊「安裝」;
- 安裝好后拔插一下 USB,看看串口號有沒有變,有變更換一下串口號;
- 最后點「打開」或者「打開串口」就可以啦。
如果還不明白的,可以參考下文,有圖文教程:
【零基礎快速上手STM32開發(手把手保姆級教程)】
5.2.1 測試模塊是否正常(AT)
發送 AT
,ESP8266 回復 OK,就是正常啟動了。
5.2.2 開啟/關閉回顯(ATE1/ATE0)
發送了指令 AT
,模塊回復了「AT OK」,即模塊將發送過來的指令原封不動的先復述了一遍后接著發送有效回復,我們稱這種復述為 回顯 。
發送 ATE0
,關閉回顯
發送 ATE1
,開啟回顯
5.2.3 設置AP模式及AP參數(AT+CWMODE,AT+CWSAP)
發送 AT+CWMODE?
,查詢模塊當前處于哪一種模式;
發送 AT+CWMODE=1
,設置 STA 模式;
發送 AT+CWMODE=2
,設置 AP 模式;
發送 AT+CWMODE=3
,設置 AP+STA 模式。
如果當前為 AP 模式,那么發送 AT+CWSAP="SSID","password",通道,加密方式
,可以設置熱點。這個過程相當于給路由器設置熱點名稱及密碼,方便手機連接。
例如:發送 AT+CWSAP="ESP8266-liangxu","12345678",5,3
,則可以將熱點名設置為 ESP8266-liangxu ,密碼為 12345678,使用通道 5 ,加密方式為 WPA2_PSK(1-WEP,2-WPA_PSK,3-WPA2_PSK,4-WPA_WPA2_PSK),這里的通道對應的就是不同的射頻頻率,如果同一空間內存在相同通道的 WIFI 信號,將會產生干擾,影響上網質量,因此可以設置通道來避免這種干擾,常用的通道有 1、6、11,因為這三個通道互不產生干擾。
5.2.4 設置為STA模式(AT+CWMODE=1,AT+CWJAP,AT+CIFSR)
發送 AT+CWMODE=1
,設置 STA 模式;
發送 AT+CWJAP="SSID","password"
,連接路由器;
發送 AT+CIPSTA?
,路由器分配給 ESP8266 的局域網 IP 以及網關地址和子網掩碼;
發送 AT+CIFSR
,查詢 ESP8266 的 IP 地址信息。
5.2.5 TCP透傳
5.2.5.1 準備工作
實現 TCP 透傳需要搭建一個 TCP 服務器,這里我們就使用網絡調試助手 + 自己的電腦就好。我的網絡調試助手是正點原子的,大家不一定要用我的,只要是網絡助手都可以。
首先我們需要知道自己電腦的 IP 地址,有兩種方式:
方法1:打開電腦的設置:
方法2:使用命令提示符:
打開網絡調試助手,跟我配置,超快的。端口號 TCP 協議一般填8080。
5.2.5.2 正式開始
接下來我們利用串口助手將 ESP8266 連接到 TCP 服務器。
發送 AT+CIPSTART="協議模式","服務端IP地址",端口號
,建立連接,協議模式有 TCP 和 UDP ;
因為我們剛剛搭建的是 TCP 服務器,服務器 IP 地址是 192.168.1.27,所以我們發送 AT+CIPSTART="TCP","192.168.1.27",8080
。如果不出意外,過一會兒 ESP8266 就連接上 TCP 服務器了,將返回 CONNECT OK 。
但這個時候,我們再在輸入框發送內容的話,依然是默認為指令。如果我們想把數據直接發送給 TCP 服務器,那么就需要開啟透傳模式。
所謂的透傳模式,可以視為 ESP8266 為透明狀態,客戶端發送的信息直接就傳輸給服務端。
我們需要先發送 AT+CIPMODE=1
,開啟透傳模式。然后,再發送 AT+CIPSEND
,才真正開始透傳發送。
此時,你發送的任何數據,就直接傳輸到服務器了。
退出透傳:先發送 +++(不要帶回車),再發送 AT+CIPMODE=0
。
如果不退出透傳,發出來的就算是 AT 指令,它也會被認為是普通字符串,直接透傳給對方。
AT+CWCLOSE
,斷開 TCP 連接。
AT+CWQAP
,斷開熱點。
6. 編程實戰
6.1 硬件接線
本教程使用的硬件如下:
單片機:STM32F103C8T6
WiFi模塊:ESP-01S
串口:USB 轉 TTL
燒錄器:ST-LINK V2。
接線可參照下表:
ESP8266 | STM32 | USB 轉 TTL |
---|---|---|
3V3 | 3.3 | |
TX | A3 | |
RX | A2 | |
GND | G | |
A10 | TX | |
A9 | RX | |
G | GND |
燒錄的時候接線如下表,如果不會燒錄的話可以看我之前的文章【STM32下載程序的五種方法】。
ST-Link V2 | STM32 |
---|---|
SWCLK | SWCLK |
SWDIO | SWDIO |
GND | GND |
3.3V | 3V3 |
其中 USB 轉 TTL 連接的是 STM32 的串口1(A9和A10),用來打印 STM32 的輸出;STM32 的串口2(A2和A3),用來控制 ESP8266。
接好就像這樣:
6.2 模板工程加載ESP8266模塊代碼
打開模板工程和 ESP8266 驅動源碼。

復制好后打開工程。
跟著我的貪吃蛇點點點:)
6.3 串口通訊實現
實現向串口發送數據,并等待返回值。ESP8266 的 TX 和 RX 定義在串口2。
- 定義串口句柄
g_uart_handle
,并調用HAL_UART_Init
進行初始化。
UART_HandleTypeDef g_uart_handle;void esp8266_uart_init(uint32_t baudrate)
{g_uart_handle.Instance = ESP8266_UART_INTERFACE; /* ESP8266 UART */g_uart_handle.Init.BaudRate = baudrate; /* 波特率 */g_uart_handle.Init.WordLength = UART_WORDLENGTH_8B; /* 數據位 */g_uart_handle.Init.StopBits = UART_STOPBITS_1; /* 停止位 */g_uart_handle.Init.Parity = UART_PARITY_NONE; /* 校驗位 */g_uart_handle.Init.Mode = UART_MODE_TX_RX; /* 收發模式 */g_uart_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* 無硬件流控 */g_uart_handle.Init.OverSampling = UART_OVERSAMPLING_16; /* 過采樣 */HAL_UART_Init(&g_uart_handle); /* 使能ESP8266 UART */
}
其中,ESP8266_UART_INTERFACE
是宏定義,指代的就是 USART2
。
傳入參數 baudrate
可以定義該串口的波特率。
- 初始化串口底層函數,調用
HAL_UART_MspInit
函數。
注意最后一行,需要調用 __HAL_UART_ENABLE_IT
函數使能接收中斷。
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{GPIO_InitTypeDef gpio_init_struct;if (huart->Instance == USART_UX) /* 如果是串口1,進行串口1 MSP初始化 */{....// 省略串口1相關代碼....}else if (huart->Instance == ESP8266_UART_INTERFACE) /* 如果是ESP8266 UART */{ESP8266_UART_TX_GPIO_CLK_ENABLE(); /* 使能UART TX引腳時鐘 */ESP8266_UART_RX_GPIO_CLK_ENABLE(); /* 使能UART RX引腳時鐘 */ESP8266_UART_CLK_ENABLE(); /* 使能UART時鐘 */gpio_init_struct.Pin = ESP8266_UART_TX_GPIO_PIN; /* UART TX引腳 */gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 復用推挽輸出 */gpio_init_struct.Pull = GPIO_NOPULL; /* 無上下拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */HAL_GPIO_Init(ESP8266_UART_TX_GPIO_PORT, &gpio_init_struct); /* 初始化UART TX引腳 */gpio_init_struct.Pin = ESP8266_UART_RX_GPIO_PIN; /* UART RX引腳 */gpio_init_struct.Mode = GPIO_MODE_INPUT; /* 輸入 */gpio_init_struct.Pull = GPIO_NOPULL; /* 無上下拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */HAL_GPIO_Init(ESP8266_UART_RX_GPIO_PORT, &gpio_init_struct); /* 初始化UART RX引腳 */HAL_NVIC_SetPriority(ESP8266_UART_IRQn, 0, 0); /* 搶占優先級0,子優先級0 */HAL_NVIC_EnableIRQ(ESP8266_UART_IRQn); /* 使能UART中斷通道 */__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE); /* 使能UART接收中斷 */}
}
- 使用接收中斷+超時判斷,完成數據接收。
由于 ESP8266 通過串口返回的數據長度不固定,所以我們可以使用接收中斷+超時判斷的方法完成數據接收。具體方法可以參考下文:
【STM32串口接收不定長數據(接收中斷+超時判斷)】
在串口中斷服務函數里,我們可以將接收到的字符保存在接收緩沖區里 g_uart_rx_buf
,并定義一個變量 esp8266_cnt
計算總共收到了多少個字符。
void ESP8266_UART_IRQHandler(void)
{uint8_t receive_data = 0; if(__HAL_UART_GET_FLAG(&g_uart_handle, UART_FLAG_RXNE) != RESET){if(esp8266_cnt >= sizeof(g_uart_rx_buf))esp8266_cnt = 0; //防止串口被刷爆HAL_UART_Receive(&g_uart_handle, &receive_data, 1, 1000);//串口2接收1位數據g_uart_rx_buf[esp8266_cnt++] = receive_data; }HAL_UART_IRQHandler(&g_uart_handle);
}
假如一幀的數據接收完成了,那么 esp8266_cnt
變量的值應該維持不變。
我們通過 while 死循環不停計算當前收到多少個字符,當前統計的值計算在 esp8266_cnt
變量里,定義另一個變量 esp8266_cntPre
,用于記錄上一次統計接收到的數據的長度,如果本次統計數據長度跟上一次一樣的話就說明數據接收完成了。代碼如下:
uint8_t esp8266_wait_receive(void)
{if(esp8266_cnt == 0) //如果接收計數為0 則說明沒有處于接收數據中,所以直接跳出,結束函數return ESP8266_ERROR;if(esp8266_cnt == esp8266_cntPre) { //如果上一次的值和這次相同,則說明接收完畢esp8266_cnt = 0; //清0接收計數return ESP8266_EOK; //返回接收完成標志}esp8266_cntPre = esp8266_cnt; //置為相同return ESP8266_ERROR; //返回接收未完成標志
}
當然,接收到的數據使用完成之后,我們就應該清空接收緩沖區,并將計數器置 0 ,方便下一次接收。
void esp8266_clear(void)
{memset(g_uart_rx_buf, 0, sizeof(g_uart_rx_buf));esp8266_cnt = 0;
}
接下來,就是最關鍵的一個函數了。我們使用這個函數通過串口向 ESP8266 發送一個字符串,并循環等待我們所期待得到的字符串。
在下面這個函數里,cmd
變量是我們向 ESP8266 發送的字符串,res
變量是我們期待得到的回復。
比如,我們向 ESP8266 發送 AT
這個字符串,那么 ESP8266 如果正常的話應該會回復 OK
。此時,cmd
就是 AT
,而 res
就是 OK
。
uint8_t esp8266_send_command(char *cmd, char *res)
{uint8_t timeOut = 250;esp8266_clear();HAL_UART_Transmit(&g_uart_handle, (unsigned char *)cmd, strlen((const char *)cmd), 100);while(timeOut--) {if(esp8266_wait_receive() == ESP8266_EOK) { //如果收到數據if(strstr((const char *)g_uart_rx_buf, res) != NULL) //如果檢索到關鍵詞return ESP8266_EOK;}delay_ms(10);}return ESP8266_ERROR;
}
6.4 編程實現AT指令交互
接下來,我們就可以使用 esp8266_send_command
發送 AT 指令并確定 ESP8266 回復是否正確。以代碼方式實現各個 AT 指令,例子如下:
uint8_t esp8266_at_test(void)
{return esp8266_send_command("AT\r\n", "OK");
}uint8_t esp8266_sw_reset(void)
{return esp8266_send_command("AT+RST\r\n", "OK");
}uint8_t esp8266_set_mode(uint8_t mode)
{switch (mode) {case ESP8266_STA_MODE:return esp8266_send_command("AT+CWMODE=1\r\n", "OK"); /* Station模式 */case ESP8266_AP_MODE:return esp8266_send_command("AT+CWMODE=2\r\n", "OK"); /* AP模式 */case ESP8266_STA_AP_MODE:return esp8266_send_command("AT+CWMODE=3\r\n", "OK"); /* AP+Station模式 */default:return ESP8266_EINVAL;}
}
由于 AT 指令有很多,這里只截取了其中的一部分,完整的可以參考我提供的代碼。
6.5 編程實現STA模式
STA 模式實現思路如下:
- 進入 STA 模式(要重啟生效);
- 設置單路連接;
- 連接 WIFI(注意 ESP8266 和服務端要在同一網絡內);
- 淺查一下 ESP8266 的 IP 地址,不查也可以;
- 連接TCP服務器;
- 開啟透傳。
uint8_t esp8266_single_connection(void)
{return esp8266_send_command("AT+CIPMUX=0\r\n", "OK");
}uint8_t esp8266_join_ap(char *ssid, char *pwd)
{char cmd[64];sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"\r\n", ssid, pwd);return esp8266_send_command(cmd, "WIFI GOT IP");
}uint8_t esp8266_get_ip(char *buf)
{char *p_start;char *p_end;if (esp8266_send_command("AT+CIFSR\r\n", "STAIP") != ESP8266_EOK)return ESP8266_ERROR;p_start = strstr((const char *)g_uart_rx_buf, "\"");p_end = strstr(p_start + 1, "\"");*p_end = '\0';sprintf(buf, "%s", p_start + 1);return ESP8266_EOK;
}uint8_t esp8266_connect_tcp_server(char *server_ip, char *server_port)
{char cmd[64];sprintf(cmd, "AT+CIPSTART=\"TCP\",\"%s\",%s\r\n", server_ip, server_port);return esp8266_send_command(cmd, "CONNECT");
}uint8_t esp8266_enter_unvarnished(void)
{uint8_t ret;ret = esp8266_send_command("AT+CIPMODE=1\r\n", "OK");ret += esp8266_send_command("AT+CIPSEND\r\n", ">");if (ret == ESP8266_EOK)return ESP8266_EOK;elsereturn ESP8266_ERROR;
}/*** @brief ESP8266初始化* @param baudrate: ESP8266 UART通訊波特率* @retval ESP8266_EOK : ESP8266初始化成功,函數執行成功* ESP8266_ERROR: ESP8266初始化失敗,函數執行失敗*/
uint8_t esp8266_init(uint32_t baudrate)
{char ip_buf[16];esp8266_uart_init(baudrate); /* ESP8266 UART初始化 *//* 讓WIFI退出透傳模式 */while(esp8266_exit_unvarnished())delay_ms(500);printf("1.AT\r\n");while(esp8266_at_test())delay_ms(500);printf("2.RST\r\n");while(esp8266_sw_reset())delay_ms(500);while(esp8266_disconnect_tcp_server())delay_ms(500);printf("3.CWMODE\r\n");while(esp8266_set_mode(ESP8266_STA_MODE))delay_ms(500);printf("4.AT+CIPMUX\r\n"); //設置單路連接模式,透傳只能使用此模式while(esp8266_multi_connection())delay_ms(500);printf("5.CWJAP\r\n"); //連接WIFIprintf("%s\r\n",WIFI_SSID); while(esp8266_join_ap(WIFI_SSID, WIFI_PWD))delay_ms(1000);printf("6.CIFSR\r\n");while(esp8266_get_ip(ip_buf))delay_ms(500);printf("ESP8266 IP: %s\r\n", ip_buf);printf("7.CIPSTART\r\n");while(esp8266_connect_tcp_server(TCP_SERVER_IP, TCP_SERVER_PORT))delay_ms(500);printf("8.CIPMODE\r\n");while(esp8266_enter_unvarnished())delay_ms(500);printf("ESP8266初始化完成\r\n");return ESP8266_EOK;
}
代碼完成,編譯,燒錄,打開串口,串口輸出,實現效果當當當:

6.6 編程實現AP模式
AP 模式實現思路很簡單:
- 進入 AP 模式(要重啟生效);
- 設置 AP 參數;
- 開啟多連接或單連接。
uint8_t esp8266_set_ap(char *ssid, char *pwd)
{char cmd[64];sprintf(cmd, "AT+CWSAP=\"%s\",\"%s\",5,3\r\n", ssid, pwd);return esp8266_send_command(cmd, "OK");
}uint8_t esp8266_multi_connection(void)
{return esp8266_send_command("AT+CIPMUX=1\r\n", "OK");
}uint8_t esp8266_init(uint32_t baudrate)
{char ip_buf[16];esp8266_uart_init(baudrate); /* ESP8266 UART初始化 *//* 讓WIFI退出透傳模式 */while(esp8266_exit_unvarnished())delay_ms(500);printf("1.AT\r\n");while(esp8266_at_test())delay_ms(500);printf("2.RST\r\n");while(esp8266_sw_reset())delay_ms(500);while(esp8266_disconnect_tcp_server())delay_ms(500);printf("3.CWMODE\r\n");while(esp8266_set_mode(ESP8266_AP_MODE))delay_ms(500);printf("4.CWSAP\r\n"); //設置APprintf("%s\r\n",WIFI_SSID); while(esp8266_set_ap(WIFI_SSID, WIFI_PWD))delay_ms(1000);printf("5.AT+CIPMUX\r\n"); //設置多路連接模式while(esp8266_multi_connection())delay_ms(500);printf("ESP8266_Init OK\r\n");return ESP8266_EOK;
}
代碼完成,燒錄,打開串口,串口輸出,實現效果當當當:
6.7 編程實現AP+STA模式
AP+STA 模式使用不多,就是前兩個的結合,這里就不多介紹了。仿照 STA 模式和 AP 模式寫相應的 AT 指令代碼就好啦,思路如下,需要注意的是要啟動多連接:
- 設置為 AP+STA 模式(要重啟生效);
- AT+CWJAP=”SSID”,”password”,連接WIFI(注意 ESP8266 和服務端要在同一網絡內);
- AT+CWSAP="SSID","password",通道,加密方式,設置AP熱點;
- AT+CIPMUX=1,啟動多連接;
- AT+CIPSERVER=1,8080,打開服務器端口為8080。
uint8_t esp8266_join_ap(char *ssid, char *pwd)
{char cmd[64];sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"\r\n", ssid, pwd);return esp8266_send_command(cmd, "WIFI GOT IP");
}uint8_t esp8266_set_ap(char *ssid, char *pwd)
{char cmd[64];sprintf(cmd, "AT+CWSAP=\"%s\",\"%s\",5,3\r\n", ssid, pwd);return esp8266_send_command(cmd, "OK");
}uint8_t esp8266_multi_connection(void)
{return esp8266_send_command("AT+CIPMUX=1\r\n", "OK");
}uint8_t esp8266_open_server()
{return esp8266_send_command("AT+CIPSERVER=1,8080\r\n", "OK");
}uint8_t esp8266_init(uint32_t baudrate)
{char ip_buf[16];esp8266_uart_init(baudrate); /* ESP8266 UART初始化 *//* 讓WIFI退出透傳模式 */while(esp8266_exit_unvarnished())delay_ms(500);/* STA+AP模式 */printf("1.AT\r\n");while(esp8266_at_test())delay_ms(500);printf("2.RST\r\n");while(esp8266_sw_reset())delay_ms(500);while(esp8266_disconnect_tcp_server())delay_ms(500);printf("3.CWMODE\r\n");while(esp8266_set_mode(ESP8266_STA_AP_MODE))delay_ms(500);printf("4.CWJAP\r\n"); //連接WIFIprintf("%s\r\n",WIFI_SSID); while(esp8266_join_ap(WIFI_SSID, WIFI_PWD))delay_ms(1000);printf("5.CWSAP\r\n"); //設置APwhile(esp8266_set_ap("ESP8266-liangxu", "12345678"))delay_ms(1000);printf("6.AT+CIPMUX\r\n"); //設置多路連接模式while(esp8266_multi_connection())delay_ms(500);printf("7.CIPSERVER\r\n"); //打開服務器端口8080while(esp8266_open_server())delay_ms(500);printf("ESP8266_Init OK\r\n");return ESP8266_EOK;
}
代碼完成,編譯,燒錄,打開串口,串口輸出,實現效果當當當:
esp8266.h文件內容如下:
#ifndef __ESP8266_H__
#define __ESP8266_H__#include <stdint.h>
#include "usart.h"extern UART_HandleTypeDef g_uart_handle;/* 引腳定義 */
#define ESP8266_UART_TX_GPIO_PORT GPIOA
#define ESP8266_UART_TX_GPIO_PIN GPIO_PIN_2
#define ESP8266_UART_TX_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PC口時鐘使能 */#define ESP8266_UART_RX_GPIO_PORT GPIOA
#define ESP8266_UART_RX_GPIO_PIN GPIO_PIN_3
#define ESP8266_UART_RX_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PD口時鐘使能 */#define ESP8266_UART_INTERFACE USART2
#define ESP8266_UART_IRQn USART2_IRQn
#define ESP8266_UART_IRQHandler USART2_IRQHandler
#define ESP8266_UART_CLK_ENABLE() do{ __HAL_RCC_USART2_CLK_ENABLE(); }while(0) /* UART2時鐘使能 *//* UART收發緩沖大小 */
#define ESP8266_UART_RX_BUF_SIZE 128
#define ESP8266_UART_TX_BUF_SIZE 64/* 錯誤代碼 */
#define ESP8266_EOK 0 /* 沒有錯誤 */
#define ESP8266_ERROR 1 /* 通用錯誤 */
#define ESP8266_ETIMEOUT 2 /* 超時錯誤 */
#define ESP8266_EINVAL 3 /* 參數錯誤 *//* 工作模式 */
#define ESP8266_STA_MODE 1
#define ESP8266_AP_MODE 2
#define ESP8266_STA_AP_MODE 3#define WIFI_SSID "HuaweiAP-1ED0"
#define WIFI_PWD "87654321"#define TCP_SERVER_IP "192.168.1.27"
#define TCP_SERVER_PORT "8080"uint8_t esp8266_init(uint32_t baudrate);
void esp8266_clear(void);
void esp8266_uart_printf(char *fmt, ...);
#endif
7. 小結
通過學習和實踐,希望大家能夠了解并掌握 ESP8266 的特性和使用,從而更好地應用于嵌入式開發。無論是構建智能家居系統還是開發物聯網設備,ESP8266 都可以成為您的得力助手,讓我們一起玩轉 ESP8266,love and peace!
另外,想進大廠的同學,一定要好好學算法,這是面試必備的。這里準備了一份 BAT 大佬總結的 LeetCode 刷題寶典,很多人靠它們進了大廠。
刷題 | LeetCode算法刷題神器,看完 BAT 隨你挑!
有收獲?希望老鐵們來個三連擊,給更多的人看到這篇文章
推薦閱讀:
- 程序員必備編程資料大全
- 程序員必備軟件資源
歡迎關注我的博客:良許嵌入式教程網,滿滿都是干貨!