一、ESP8265概述
????????官方網址:ESP8266 Wi-Fi MCU I 樂鑫科技 (espressif.com.cn)
ESP8266 是什么?
????????ESP8266 是由樂鑫科技(Espressif Systems)開發的一款低成本、高性能的 Wi-Fi 微控制器芯片 / 模塊,集成了 32 位 Tensilica L106 處理器、Wi-Fi 射頻(802.11 b/g/n)、TCP/IP 協議棧,以及豐富的 GPIO 引腳和外設接口(I2C、SPI、UART 等)。
????????????????它的核心優勢是 **“低成本實現 Wi-Fi 聯網”**—— 相比傳統的 “MCU + 獨立 Wi-Fi 模塊” 方案,ESP8266 直接將處理器和 Wi-Fi 功能集成,成本可低至幾美元,且體積小巧(常見模塊如 ESP-12F 尺寸僅 24mm×16mm),因此成為物聯網(IoT)領域的 “明星產品”。
ESP8266 能干什么?
ESP8266 的核心功能是 **“讓設備接入 Wi-Fi 網絡”**,因此被廣泛用于需要聯網的場景,典型應用包括:
- 物聯網(IoT)設備:如智能傳感器(溫濕度、光照、煙霧傳感器)的數據上傳(發送到云端服務器或手機);
- 智能家居:控制燈光、窗簾、空調等設備(通過 Wi-Fi 接收手機 APP 指令);
- 遠程監控:連接攝像頭或傳感器,實時向手機推送數據;
- Wi-Fi 網關:將其他協議(如藍牙、ZigBee)的設備數據轉換為 Wi-Fi 信號轉發;
- 簡易服務器:作為小型 Web 服務器,通過瀏覽器直接控制設備(例如網頁按鈕控制燈光開關)。
1. ESP8266中的wifi:
? ? ? ? ?ESP8266EX支持TCP/IP協議,完全遵循802.11 b/g/n WLAN MAC協議,支持分布式控制功能(DCF)下的基本服務集(BSS)STA和SoftAP操作。支持通過最小化主機交互來優化有效工作時長,以實現功耗管理。
? ? ? ? ?我們主要使用esp8266的wifi功能:
2.AT指令集的概念:
3. ESP8266引腳:

?需要配置的引腳:
1. 復位:
3.? 電源部分:
4.? 串口
以下為單片機與ESP8266的連接方式:
啟動模式:
?????????程序正常運行,我們需要保證使能位和RST,必須拉高
二、ESP8266的聯網步驟
步驟 | AT 指令(串口發送) | 期望返回 | 作用說明 |
---|---|---|---|
1 | AT+CWMODE=1 | OK | 設為 STA 模式 |
2 | AT+RST | 重啟日志 +?ready ?+?OK | 重啟生效模式 |
3 | AT+CWJAP="MyWiFi","1234" | WIFI CONNECTED WIFI GOT IP OK | 連 Wi-Fi 成功 |
4 | AT+CIPMUX=0 | OK | 設為單連接模式 |
5 | AT+CIPSTART="TCP","192.168.1.100",8888 | CONNECT OK | 連 TCP 服務器成功 |
6 | AT+CIPMODE=1 | OK | 開透傳模式 |
7 | AT+CIPSEND | > | 進入透傳,可直接發數據 |
8 | Hello Server! | (無返回,直接傳給服務器) | 透傳數據 |
9 | +++ (發之前停 1 秒) | OK | 退出透傳,切回 AT 指令模式 |
1.?
AT+CWMODE=1
:設置工作模式(STA 模式)
- 作用:讓 ESP8266 作為「Station(站點)」,即像手機、電腦一樣,去連接外部 Wi-Fi 熱點。
- 模式說明:
Station:用作客戶端,是需要連接路由器或者熱點SoftAP:用作服務器端,本身可以作為熱點使用SoftAP+Station:混合模式。- 實操:
串口發送?AT+CWMODE=1
,收到?OK
?則設置成功。
2.?
AT+RST
:模塊重啟(讓工作模式生效)
- 作用:ESP8266 是 “單片機思維”,改完模式后需重啟才能真正切換。
- 細節:
發送?AT+RST
?后,模塊會重啟,串口會打印一堆啟動日志(如?ready
?等),最后回到可接收 AT 指令狀態。
3.?
AT+CWJAP="SSID","PASSWORD"
:連接 Wi-Fi 熱點
- 作用:讓 ESP8266 接入你指定的 Wi-Fi 網絡。
- 參數說明:
SSID
:你要連的 Wi-Fi 名稱(字符串,必須用英文雙引號包裹)PASSWORD
:Wi-Fi 密碼(同理,英文雙引號包裹,無密碼則填?""
?)- 實操:
比如連名為?MyWiFi
、密碼?12345678
?的 Wi-Fi,發送:等待幾秒,收到?AT+CWJAP="MyWiFi","12345678"
WIFI CONNECTED
(連成功) +?WIFI GOT IP
(分配到 IP) +?OK
,則聯網完成。
4.?
AT+CIPMUX=0
:設置單路連接模式
- 作用:告訴模塊,接下來要建立?1 對 1 的 TCP/UDP 連接(單連接模式)。
- 模式說明:
CIPMUX=0
:單連接(同一時間只能連 1 個服務器)CIPMUX=1
:多連接(可同時連多個服務器,需配合?AT+CIPSERVER
?等指令)- 何時用:
如果你只是想連一個服務器(比如傳數據到自己的云平臺),選?0
?更簡單。
5.?
AT+CIPSTART="TCP","IP地址",端口號
:建立 TCP 連接
- 作用:讓 ESP8266 主動連到你指定的 TCP 服務器(比如自己電腦開的 TCP 服務、云平臺)。
- 參數說明:
TCP
:協議類型(也支持?UDP
,按需換)IP地址
:服務器的公網 / 局域網 IP(比如本地調試填?192.168.1.100
,云平臺填?47.xxx.xxx.xxx
?)端口號
:服務器監聽的端口(如?8080
?3333
,需和服務器程序對應)- 實操:
比如連本地電腦(IP?192.168.1.100
,端口?8888
)的 TCP 服務,發送:收到?AT+CIPSTART="TCP","192.168.1.100",8888
CONNECT OK
?則連接成功,失敗會返回?CONNECT FAIL
(檢查 IP、端口、服務器是否開啟)。
6.?
AT+CIPMODE=1
:開啟透傳模式
- 作用:進入「透傳」狀態 —— 你從串口發的所有數據,會直接透傳給 TCP/UDP 服務器,無需額外加指令頭(反之,服務器發的數據也會直接返回串口)。
- 對比普通模式:
- 普通模式(
CIPMODE=0
)發數據,需先?AT+CIPSEND=長度
,再發內容(麻煩);- 透傳模式(
CIPMODE=1
)發數據,直接敲內容就行(簡單,適合持續傳數據)。
7.?
AT+CIPSEND
:進入透傳數據發送
- 作用:在透傳模式下,執行這條指令后,模塊進入 “數據直通” 狀態。
- 實操:
發送?AT+CIPSEND
?后,串口會返回?>
,此時你輸入的任何內容(比如?Hello Server!
?),都會直接通過 TCP 發給服務器,無需額外處理。
8.?
+++
:退出透傳模式
- 作用:從透傳狀態切回 “AT 指令模式”,方便你發其他 AT 指令(比如斷網、改配置)。
- 關鍵細節:
發?+++
?時,必須保證串口沒有其他數據同時發送(即發?+++
?前后,要等 1 秒左右無數據,否則模塊可能識別成普通數據)。
成功退出后,串口會返回?OK
,此時可繼續發?AT+CWQAP
(斷開 Wi-Fi)等指令。
?
三、具體代碼案例
1.esp8266.c:
#include "esp8266.h"
#include "delay.h"
#include "stdio.h"
#include "string.h"
#include "esp_data.h"
//配置串口+ESP8266使能和復位
void usart3_Init(u32 brr)
{GPIO_InitTypeDef GPIOInitTypeDef;USART_InitTypeDef USARTInitTypeDef;//打開時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//配置PB10--TX PB11--RX//PB10--復用推挽輸出GPIOInitTypeDef.GPIO_Pin=GPIO_Pin_10;GPIOInitTypeDef.GPIO_Mode=GPIO_Mode_AF_PP;GPIOInitTypeDef.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIOInitTypeDef);//PB11--浮空GPIOInitTypeDef.GPIO_Pin=GPIO_Pin_11;GPIOInitTypeDef.GPIO_Mode=GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOB,&GPIOInitTypeDef);//usart3的配置USARTInitTypeDef.USART_BaudRate=brr;USARTInitTypeDef.USART_HardwareFlowControl=USART_HardwareFlowControl_None;USARTInitTypeDef.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;USARTInitTypeDef.USART_Parity=USART_Parity_No;USARTInitTypeDef.USART_StopBits=USART_StopBits_1;USARTInitTypeDef.USART_WordLength=USART_WordLength_8b;USART_Init(USART3,&USARTInitTypeDef);usart3_It_Config();USART_Cmd(USART3,ENABLE);
}
//配置中斷 接收和空閑
void usart3_It_Config(void)
{//設置空閑中斷和接收中斷USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);USART_ITConfig(USART3,USART_IT_IDLE,ENABLE);//NVIC_SetPriority(USART3_IRQn,0);//占先優先級:1 次級優先級:1 NVIC_EnableIRQ(USART3_IRQn);
}void ESP8266_IO_Config(void)
{GPIO_InitTypeDef gpio_initsources;//打開時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);gpio_initsources.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_14;gpio_initsources.GPIO_Mode=GPIO_Mode_Out_PP;gpio_initsources.GPIO_Speed=GPIO_Speed_2MHz;//配置PB5//void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);GPIO_Init(GPIOG,&gpio_initsources);
}
//聯網流程
u8 Esp8266_AT_test(void)
{//"AT\r\n"char count=0;GPIO_SetBits ( GPIOG, GPIO_Pin_13 );GPIO_SetBits ( GPIOG, GPIO_Pin_14 );printf("\r\nAT測試.....\r\n");delay_ms ( 2000 );while ( count < 10 ){printf("\r\nAT測試次數 %d......\r\n", count);if( ESP8266_Cmd ( "AT", "OK",NULL,500) ){printf("\r\nAT測試啟動成功 %d......\r\n", count);return 1;}//復位以下GPIO_ResetBits ( GPIOG, GPIO_Pin_14 );delay_ms ( 500 ); GPIO_SetBits ( GPIOG, GPIO_Pin_14 );++ count;}return 0;
}
//AT+CWMODE=1
bool ESP8266_SetMode(u8 mode)
{char esp_cmd[100];
// switch(mode)
// {
// case 1:sprintf(esp_cmd,"AT+CWMODE=%d",mode);break;
// case 2:sprintf(esp_cmd,"AT+CWMODE=%d",mode);break;
// case 3:sprintf(esp_cmd,"AT+CWMODE=%d",mode);break
// }
// sprintf(esp_cmd,"AT+CWMODE=%d",mode);return (ESP8266_Cmd(esp_cmd,"OK",NULL,500));}
//設置聯網熱點
//AT+CWJAP="111","11111111"
bool ESP8266_SET_HotPort(void)
{char esp_cmd[100];sprintf(esp_cmd,"AT+CWJAP=\"%s\",\"%s\"",WIFI_ID,WIFI_PW);return (ESP8266_Cmd(esp_cmd,"OK",NULL,500));}
//AT+CIPMUX=0--單鏈接
bool ESP8266_Set_CIPmux(u8 cipmux)
{char esp_cmd[100];sprintf(esp_cmd,"AT+CIPMUX=%d",cipmux);return (ESP8266_Cmd(esp_cmd,"OK",NULL,500));}bool ESP8266_Set_CIPSTART(u8 link_id)
{char esp_cmd[100];//整理需要發送的指令格式if(link_id<5){//多鏈接}else {//單鏈接//AT+CIPSTART="TCP","iot.espressif.cn",8000sprintf(esp_cmd,"AT+CIPSTART=\"%s\",\"%s\",%d","TCP",SER_IP,SER_PORT);}return (ESP8266_Cmd(esp_cmd,"OK","ALREADY CONNECT",500));}u8 ESP8266_Send_Data(void)
{//設置透傳模式if ( ! ESP8266_Cmd ( "AT+CIPMODE=1", "OK", 0, 500 ) )return false;//開始數據傳輸return //必須接收到 “>”,然后才可以進入透傳模式ESP8266_Cmd ( "AT+CIPSEND", "OK", ">", 500 );
}void ESP8266_NET_Config(void)
{GPIO_SetBits ( GPIOG, GPIO_Pin_13 );//使能ESP8266printf("配置ESP8266聯網流程\r\n");//聯網流程
// Esp8266_AT_test();while(!Esp8266_AT_test());//printf("正在配置ESP8266模式\r\n");while(!ESP8266_SetMode(1));printf("正在配置WIFI熱點信息\r\n");while(!ESP8266_SET_HotPort());printf("正在配置單鏈接\r\n");while(!ESP8266_Set_CIPmux(0));//printf("正在配置服務器端信息\r\n");while(!ESP8266_Set_CIPSTART(5));//透傳模式配置printf("進入透傳模式\r\n");while(!ESP8266_Send_Data());printf("進入透傳模式成功\r\n");printf("開始傳輸數據\r\n");}
對應的.h文件:
#ifndef _ESP8266_H_
#define _ESP8266_H_
#include "stm32f10x.h"
#include <stdbool.h>//enum{
// Station=1,
// SoftAP,
// SoftSta
//}Cmode;
#define WIFI_ID "iPhone010" //熱點ID
#define WIFI_PW "66666666" //熱點密碼#define SER_IP "" //連接的服務器的ip,建議為云服務器,因為有公網ip
#define SER_PORT 8000 //端口號void usart3_Init(u32 brr);
void usart3_It_Config(void);
void ESP8266_IO_Config(void);
u8 Esp8266_AT_test(void);
bool ESP8266_SetMode(u8 mode);
bool ESP8266_SET_HotPort(void);
bool ESP8266_Set_CIPmux(u8 cipmux);
bool ESP8266_Set_CIPSTART(u8 link_id);u8 ESP8266_Send_Data(void);
void ESP8266_NET_Config(void);#endif
2.esp_data.c:
#include "esp_data.h"
#include "stdarg.h"
#include "string.h"
#include <stdbool.h>
#include <delay.h>
#include <stdio.h>
#include "esp8266.h"struct STRUCT_USARTx_Fram strEsp8266_Fram_Record = { 0 };
struct STRUCT_USARTx_Fram strUSART_Fram_Record = { 0 };static char *itoa( int value, char * string, int radix );void USART_printf ( USART_TypeDef * USARTx, char * Data, ... )
{const char *s;int d; char buf[16];va_list ap;va_start(ap, Data);while ( * Data != 0 ) // 判斷是否到達字符串結束符{ if ( * Data == 0x5c ) //'\'{ switch ( *++Data ){case 'r': //回車符USART_SendData(USARTx, 0x0d);Data ++;break;case 'n': //換行符USART_SendData(USARTx, 0x0a); Data ++;break;default:Data ++;break;} }else if ( * Data == '%'){ //switch ( *++Data ){ case 's': //字符串s = va_arg(ap, const char *);for ( ; *s; s++) {USART_SendData(USARTx,*s);while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );}Data++;break;case 'd': //十進制d = va_arg(ap, int);itoa(d, buf, 10);for (s = buf; *s; s++) {USART_SendData(USARTx,*s);while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );}Data++;break;default:Data++;break;} }else USART_SendData(USARTx, *Data++);while ( USART_GetFlagStatus ( USARTx, USART_FLAG_TXE ) == RESET );}
}
/** 函數名:itoa* 描述 :將整形數據轉換成字符串* 輸入 :-radix =10 表示10進制,其他結果為0* -value 要轉換的整形數* -buf 轉換后的字符串* -radix = 10* 輸出 :無* 返回 :無* 調用 :被USART2_printf()調用*/
static char * itoa( int value, char *string, int radix )
{int i, d;int flag = 0;char *ptr = string;/* This implementation only works for decimal numbers. */if (radix != 10){*ptr = 0;return string;}if (!value){*ptr++ = 0x30;*ptr = 0;return string;}/* if this is a negative value insert the minus sign. */if (value < 0){*ptr++ = '-';/* Make the value positive. */value *= -1;}for (i = 10000; i > 0; i /= 10){d = value / i;if (d || flag){*ptr++ = (char)(d + 0x30);value -= (d * i);flag = 1;}}/* Null terminate the string. */*ptr = 0;return string;} /* NCL_Itoa *///1---成功 0--失敗
bool ESP8266_Cmd ( char * cmd, char * reply1, char * reply2, u32 waittime )
{ strEsp8266_Fram_Record .InfBit .FramLength = 0; //從新開始接收新的數據包macESP8266_Usart ( "%s\r\n", cmd );if ( ( reply1 == 0 ) && ( reply2 == 0 ) ) //不需要接收數據return true;delay_ms ( waittime ); //延時strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = '\0';printf("000\r\n");macPC_Usart ( "00%s", strEsp8266_Fram_Record .Data_RX_BUF );strEsp8266_Fram_Record .InfBit .FramLength = 0; //清除接收標志strEsp8266_Fram_Record.InfBit.FramFinishFlag = 0; if ( ( reply1 != 0 ) && ( reply2 != 0 ) )return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) || ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) ); else if ( reply1 != 0 )return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) );elsereturn ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) );}u8 ucTcpClosedFlag=0;
void USART1_IRQHandler(void)
{uint8_t ucCh;if ( USART_GetITStatus ( USART1, USART_IT_RXNE ) != RESET ){ucCh = USART_ReceiveData( USART1 );if ( strUSART_Fram_Record .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) ) //預留1個字節寫結束符strUSART_Fram_Record .Data_RX_BUF [ strUSART_Fram_Record .InfBit .FramLength ++ ] = ucCh;}if ( USART_GetITStatus( USART1, USART_IT_IDLE ) == SET ) //數據幀接收完畢{strUSART_Fram_Record .InfBit .FramFinishFlag = 1; ucCh = USART_ReceiveData( USART1 ); //由軟件序列清除中斷標志位(先讀USART_SR,然后讀USART_DR) }
}/*** @brief This function handles macESP8266_USARTx Handler.* @param None* @retval None*/
void USART3_IRQHandler ( void )
{ uint8_t ucCh;if ( USART_GetITStatus ( USART3, USART_IT_RXNE ) != RESET ){ucCh = USART_ReceiveData( USART3 );if ( strEsp8266_Fram_Record .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) ) //預留1個字節寫結束符strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ++ ] = ucCh;}if ( USART_GetITStatus( USART3, USART_IT_IDLE ) == SET ) //數據幀接收完畢{strEsp8266_Fram_Record .InfBit .FramFinishFlag = 1;ucCh = USART_ReceiveData( USART3 ); //由軟件序列清除中斷標志位(先讀USART_SR,然后讀USART_DR)ucTcpClosedFlag = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "CLOSED\r\n" ) ? 1 : 0; //獲取連接狀態} }void ESP8266_ExitUnvarnishSend ( void )
{delay_ms ( 1000 );macESP8266_Usart ( "+++" );delay_ms ( 500 ); }
uint8_t ESP8266_Get_LinkStatus ( void )
{if ( ESP8266_Cmd ( "AT+CIPSTATUS", "OK", 0, 500 ) ){if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:2\r\n" ) )return 2;else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:3\r\n" ) )return 3;else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:4\r\n" ) )return 4; }return 0;}void ESP8266_CheckRecvDataTest(void)
{uint8_t ucStatus;uint16_t i;/* 如果接收到了串口調試助手的數據 */if(strUSART_Fram_Record.InfBit.FramFinishFlag == 1){for(i = 0;i < strUSART_Fram_Record.InfBit.FramLength; i++){USART_SendData( USART3 ,strUSART_Fram_Record.Data_RX_BUF[i]); //轉發給ESP82636while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET){} //等待發送完成}strUSART_Fram_Record .InfBit .FramLength = 0; //接收數據長度置零strUSART_Fram_Record .InfBit .FramFinishFlag = 0; //接收標志置零}/* 如果接收到了ESP8266的數據 */if(strEsp8266_Fram_Record.InfBit.FramFinishFlag){ for(i = 0;i < strEsp8266_Fram_Record .InfBit .FramLength; i++) {USART_SendData( USART1 ,strEsp8266_Fram_Record .Data_RX_BUF[i]); //轉發給ESP8266while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET){}}strEsp8266_Fram_Record .InfBit .FramLength = 0; //接收數據長度置零strEsp8266_Fram_Record.InfBit.FramFinishFlag = 0; //接收標志置零}if ( ucTcpClosedFlag ) //檢測是否失去連接{ESP8266_ExitUnvarnishSend (); //退出透傳模式do ucStatus = ESP8266_Get_LinkStatus (); //獲取連接狀態while ( ! ucStatus );if ( ucStatus == 4 ) //確認失去連接后重連{printf ( "\r\n正在重連熱點和服務器 ......\r\n" );while ( !ESP8266_SET_HotPort() );//0--TCPwhile ( ! ESP8266_Set_CIPSTART(5) );printf ( "\r\n重連熱點和服務器成功\r\n" );}while ( ! ESP8266_Send_Data () ); }
}
對應的.h文件:
#ifndef _ESP_DATA_H_
#define _ESP_DATA_H_
#include "stm32f10x.h"
#include <stdio.h>
#include <stdbool.h>
#pragma anon_unions#define macESP8266_Usart( fmt, ... ) USART_printf ( USART3, fmt, ##__VA_ARGS__ )#define macPC_Usart( fmt, ... ) printf ( fmt, ##__VA_ARGS__ )
#define RX_BUF_MAX_LEN 1024 //最大接收緩存字節數
extern struct STRUCT_USARTx_Fram //串口數據幀的處理結構體
{char Data_RX_BUF [ RX_BUF_MAX_LEN ];union {__IO u16 InfAll;struct {__IO u16 FramLength :15; // 14:0 __IO u16 FramFinishFlag :1; // 15 } InfBit;}; } strEsp8266_Fram_Record;extern struct STRUCT_USARTx_Fram strUSART_Fram_Record;
void USART_printf ( USART_TypeDef * USARTx, char * Data, ... );
bool ESP8266_Cmd ( char * cmd, char * reply1, char * reply2, u32 waittime );
void ESP8266_CheckRecvDataTest(void);#endif
3. 監聽的服務器程序server.py:(可以運行在pc端監聽單片機wifi模塊發來的數據)
import socketserver_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 監聽所有可用接口,云服務器需用 0.0.0.0
server_socket.bind(('0.0.0.0', 8000))
server_socket.listen(5)print('服務器已啟動,等待客戶端連接...')while True:client_socket, client_address = server_socket.accept()print(f'客戶端 {client_address} 已連接')while True:data = client_socket.recv(1024)if not data:breakprint(f'收到數據: {data.decode("utf-8")}')client_socket.send(f"服務器已收到: {data.decode('utf-8')}".encode('utf-8'))client_socket.close()print(f'客戶端 {client_address} 已斷開')
? ? ? ? 云服務器上運行:python3 server.py?
4. main.c:
#include "stm32f10x.h"
#include "esp8266.h"
#include "delay.h"int main(void)
{// 1. 系統時鐘配置(如果使用CubeMX生成則自動完成)SystemInit();// 2. 初始化延時函數(需要實現delay.c/h)delay_init();// 3. 配置USART1(用于調試信息輸出到PC)// 假設USART1已經在其他地方初始化,波特率115200// 如果沒有,需要添加USART1_Init(115200)之類的函數調用// 4. 配置USART3(用于與ESP8266通信)usart3_Init(115200);// 5. 配置ESP8266的控制引腳(EN和RST)ESP8266_IO_Config();// 6. 啟動ESP8266并完成聯網配置printf("\r\n==== ESP8266聯網測試 ====\r\n");ESP8266_NET_Config();// 7. 主循環:持續檢查并轉發數據while(1){// 檢查并處理ESP8266與PC之間的數據轉發ESP8266_CheckRecvDataTest();// 可以添加其他業務邏輯(如讀取傳感器數據等)// 適當延時,避免CPU占用過高delay_ms(10);}
}
5.步驟與現象:
1.?串口助手觀察初始化過程
打開串口助手(波特率 115200),復位 STM32 后,應看到以下輸出:
?==== ESP8266聯網測試 ==== 配置ESP8266聯網流程 AT測試..... AT測試次數 0...... AT測試啟動成功 0...... 正在配置ESP8266模式 正在配置WIFI熱點信息 正在配置單鏈接 正在配置服務器端信息 進入透傳模式 進入透傳模式成功 開始傳輸數據
2.?云服務器日志驗證連接
Python 服務器應顯示類似日志:
?服務器已啟動,等待客戶端連接... 客戶端 ('你的ESP8266 IP', 隨機端口) 已連接
3.?數據透傳測試
PC→云服務器:
在串口助手發送任意消息(如?Hello, server!
),云服務器日志會顯示:收到數據: Hello, server!
云服務器→PC:
服務器會自動回復消息,串口助手會顯示:服務器已收到: Hello, server!
4.?斷開重連測試
手動停止云服務器上的 Python 程序,模擬斷開連接。ESP8266 會自動檢測到連接丟失,并在串口顯示:
正在重連熱點和服務器 ......
重新啟動云服務器上的 Python 程序,ESP8266 會自動重連,串口顯示:
重連熱點和服務器成功
https://github.com/0voice??