一、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
,需和服务器程序对应)- 实操:
比如连本地电脑(IP192.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